From 60669dc91fce0b3e0c250ec4fe19e6e890622ef9 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Fri, 9 Jan 2026 16:23:34 +0100 Subject: [PATCH 01/13] migrate api_test to criterion --- .gitignore | 3 + .vscode/settings.json | 5 ++ CMakeLists.txt | 16 +++--- README.md | 10 ++++ cmake/FindCriterion.cmake | 100 +++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 9 +++ api_test.c => tests/api_test.c | 58 +++++++------------ 7 files changed, 157 insertions(+), 44 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 cmake/FindCriterion.cmake create mode 100644 tests/CMakeLists.txt rename api_test.c => tests/api_test.c (74%) diff --git a/.gitignore b/.gitignore index 7fd7729..052d80b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ Makefile api_test ccos_disk_tool + +build/ +.cache/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e61237d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "clangd.arguments": [ + "--compile-commands-dir=build" + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e872e3c..50fa187 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,14 @@ cmake_minimum_required(VERSION 3.10) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + project(ccos_disk_tool) set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${SOURCE_DIR}) +option(CCOS_ENABLE_TESTS "Build and run tests (Criterion)" OFF) + add_library(ccos_api STATIC ${SOURCE_DIR}/string_utils.h ${SOURCE_DIR}/string_utils.c @@ -26,10 +30,8 @@ add_executable(ccos_disk_tool TARGET_LINK_LIBRARIES(ccos_disk_tool ccos_api) -project(api_test) - -add_executable(api_test - ${SOURCE_DIR}/api_test.c - ) - -TARGET_LINK_LIBRARIES(api_test ccos_api) +if(CCOS_ENABLE_TESTS) + include(CTest) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/README.md b/README.md index 87c3560..416aaa2 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,16 @@ OPTIONS: -l, --in-place Write changes to the original image ``` +## Tests + +To run the tests, execute these commands: + +```bash +cmake -S . -B build -DCCOS_ENABLE_TESTS=ON +cmake --build build --parallel +ctest --test-dir build --output-on-failure +``` + ## Examples ### Working with bubble memory images or other non-standard images diff --git a/cmake/FindCriterion.cmake b/cmake/FindCriterion.cmake new file mode 100644 index 0000000..cf8d8d4 --- /dev/null +++ b/cmake/FindCriterion.cmake @@ -0,0 +1,100 @@ +# This file is licensed under the WTFPL version 2 -- you can see the full +# license over at http://www.wtfpl.net/txt/copying/ +# +# Find Criterion. +# +# Module defines the following imported library: +# Criterion::Criterion +# +# Module defines the following result variables: +# Criterion_FOUND - True if the Criterion library has been found +# Criterion_INCLUDE_DIRS - Include directories needed to use Criterion +# Criterion_LIBRARIES - Libraries needed to link to Criterion +# Criterion_VERSION - The version of the Criterion which was found +# +# Cache variables: +# Criterion_INCLUDE_DIR - The directory containing criterion/criterion.h +# Criterion_LIBRARY - The path to the Criterion library +# +# Example usage: +# find_package(Criterion) +# target_link_libraries(foo PRIVATE Criterion::Criterion) + +set(_criterionReason "") + +# Try pkg-config. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Criterion QUIET criterion) +endif() + +find_path( + Criterion_INCLUDE_DIR + criterion/criterion.h + HINTS ${PC_Criterion_INCLUDE_DIRS} + DOC "The directory containing criterion/criterion.h" +) +mark_as_advanced(Criterion_INCLUDE_DIR) + +if(NOT Criterion_INCLUDE_DIR) + string(APPEND _criterionReason "criterion/criterion.h not found. ") +endif() + +find_library( + Criterion_LIBRARY + NAMES criterion libcriterion + HINTS ${PC_Criterion_LIBRARY_DIRS} + DOC "The path to the Criterion library" +) +mark_as_advanced(Criterion_LIBRARY) + +if(NOT Criterion_LIBRARY) + string(APPEND _criterionReason "Criterion library (libcriterion) not found. ") +endif() + +# Get Criterion version from pkg-config if available. Conditional check ensures +# that Criterion found by pkg-config is the one found by the find_path() and +# find_library(). +if(PC_Criterion_VERSION AND Criterion_INCLUDE_DIR IN_LIST PC_Criterion_INCLUDE_DIRS) + set(Criterion_VERSION ${PC_Criterion_VERSION}) +endif() + +include(FindPackageHandleStandardArgs) +# Handle the REQUIRED, QUIET, and version-related arguments of find_package(). +find_package_handle_standard_args( + Criterion + REQUIRED_VARS Criterion_LIBRARY Criterion_INCLUDE_DIR + VERSION_VAR Criterion_VERSION + HANDLE_VERSION_RANGE + REASON_FAILURE_MESSAGE "${_criterionReason}" +) + +unset(_criterionReason) + +if(NOT Criterion_FOUND) + return() +endif() + +set(Criterion_INCLUDE_DIRS ${Criterion_INCLUDE_DIR}) +set(Criterion_LIBRARIES ${Criterion_LIBRARY}) + +if(NOT TARGET Criterion::Criterion) + if(IS_ABSOLUTE "${Criterion_LIBRARY}") + add_library(Criterion::Criterion UNKNOWN IMPORTED) + set_target_properties( + Criterion::Criterion + PROPERTIES IMPORTED_LOCATION "${Criterion_LIBRARY}" + ) + else() + add_library(Criterion::Criterion INTERFACE IMPORTED) + set_target_properties( + Criterion::Criterion + PROPERTIES IMPORTED_LIBNAME "${Criterion_LIBRARY}" + ) + endif() + + set_target_properties( + Criterion::Criterion + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Criterion_INCLUDE_DIRS}" + ) +endif() \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..507e0c8 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +find_package(Criterion REQUIRED) + +add_executable(ccos_tests + ${CMAKE_CURRENT_LIST_DIR}/api_test.c + ) + +target_link_libraries(ccos_tests PRIVATE ccos_api Criterion::Criterion) + +add_test(NAME ccos_tests COMMAND ccos_tests) diff --git a/api_test.c b/tests/api_test.c similarity index 74% rename from api_test.c rename to tests/api_test.c index 81b48c6..3b404f1 100644 --- a/api_test.c +++ b/tests/api_test.c @@ -2,23 +2,15 @@ // Created by kirill on 04.06.2020. // +#include + #include #include -#include -#include - -#define __STR(X) #X -#define STR(X) __STR(X) -#define ASSERT(CONDITION) \ - do { \ - if (!(CONDITION)) { \ - fprintf(stderr, "%s:%d: \"%s\" Failed!\n", __FUNCTION__, __LINE__, STR(CONDITION)); \ - return -1; \ - } \ - } while (0) +#include +#include -uint8_t test_inode_data[] = { +static const uint8_t test_inode_data[] = { 0x98U, 0x00U, 0x00U, 0x00U, 0x84U, 0xD0U, 0x00U, 0x00U, 0x15U, 0x47U, 0x52U, 0x69U, 0x44U, 0x50U, 0x61U, 0x69U, 0x6EU, 0x74U, 0x7EU, 0x52U, 0x75U, 0x6EU, 0x20U, 0x43U, 0x61U, 0x6EU, 0x76U, 0x61U, 0x73U, 0x7EU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, @@ -52,43 +44,35 @@ uint8_t test_inode_data[] = { 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0x00U, 0x00U, 0x00U, 0x00U}; -int check_image_test() { +Test(ccos_image, check_image) { uint8_t data[0x200] = {0}; - ASSERT(ccos_check_image(data) == 0); + cr_assert_eq(ccos_check_image(data), 0); data[0] = 'I'; data[1] = 'M'; data[2] = 'D'; data[3] = ' '; - ASSERT(ccos_check_image(data) == -1); + cr_assert_eq(ccos_check_image(data), -1); memset(data, 0, 0x200); data[0] = 0xEB; data[2] = 0x90; *((uint16_t *)(&data[0x1FE])) = 0xAA55; - ASSERT(ccos_check_image(data) == -1); - return 0; + cr_assert_eq(ccos_check_image(data), -1); } -int ccos_get_file_version_test() { - ccos_inode_t inode = *((ccos_inode_t *)&test_inode_data); +Test(ccos_image, get_file_version) { + ccos_inode_t inode; + memcpy(&inode, test_inode_data, sizeof(inode)); version_t version = ccos_get_file_version(&inode); - ASSERT(version.major == 3); - ASSERT(version.minor == 1); - ASSERT(version.patch == 5); - return 0; + cr_assert_eq(version.major, 3); + cr_assert_eq(version.minor, 1); + cr_assert_eq(version.patch, 5); } -int ccos_get_file_name_test() { - ccos_inode_t inode = *((ccos_inode_t *)&test_inode_data); +Test(ccos_image, get_file_name) { + ccos_inode_t inode; + memcpy(&inode, test_inode_data, sizeof(inode)); short_string_t *name = ccos_get_file_name(&inode); - ASSERT(name->length == 21); - ASSERT(!strncmp(name->data, "GRiDPaint~Run Canvas~", name->length)); - return 0; -} - -int main() { - ASSERT(check_image_test() == 0); - ASSERT(ccos_get_file_version_test() == 0); - ASSERT(ccos_get_file_name_test() == 0); - printf("All tests completed!\n"); - return 0; + cr_assert_not_null(name); + cr_assert_eq(name->length, 21); + cr_assert_eq(strncmp(name->data, "GRiDPaint~Run Canvas~", name->length), 0); } From 8ca1fc8bb71059f785457da60d4a79c98fd687be Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Fri, 9 Jan 2026 16:38:44 +0100 Subject: [PATCH 02/13] enable EXPORT_COMPILE_COMMANDS by default --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50fa187..cf4a0af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.10) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") project(ccos_disk_tool) From 138436bf6b9103a23cd70cf0107fb1862ace3b53 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Sat, 10 Jan 2026 11:58:47 +0100 Subject: [PATCH 03/13] update README.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 416aaa2..16e8454 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,20 @@ OPTIONS: -l, --in-place Write changes to the original image ``` -## Tests +## Build -To run the tests, execute these commands: +To build the project, run the following commands: + +```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build --parallel +``` + +After building, the compiled binary will be located at `build/ccos_disk_tool`. + +## Run Tests + +To run the tests, use the following commands: ```bash cmake -S . -B build -DCCOS_ENABLE_TESTS=ON @@ -53,6 +64,8 @@ cmake --build build --parallel ctest --test-dir build --output-on-failure ``` +Tests depend on the [Criterion](https://github.com/Snaipe/Criterion) library, which must be installed before running the tests. + ## Examples ### Working with bubble memory images or other non-standard images From c47f22fb97a8877a59bdb89ae293786c50612731 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 00:49:24 +0100 Subject: [PATCH 04/13] rewrite disk format from scratch --- CMakeLists.txt | 3 + ccos_context.h | 9 ++ ccos_format.c | 222 +++++++++++++++++++++++++++++++++++++++++++++ ccos_format.h | 20 ++++ ccos_format_data.h | 173 +++++++++++++++++++++++++++++++++++ ccos_image.c | 19 ---- ccos_image.h | 11 +-- ccos_private.c | 111 ++--------------------- ccos_private.h | 19 ++-- main.c | 5 +- wrapper.c | 20 ++-- 11 files changed, 456 insertions(+), 156 deletions(-) create mode 100644 ccos_format.c create mode 100644 ccos_format.h create mode 100644 ccos_format_data.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cf4a0af..b4bf332 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,9 @@ add_library(ccos_api STATIC ${SOURCE_DIR}/common.c ${SOURCE_DIR}/ccos_image.h ${SOURCE_DIR}/ccos_image.c + ${SOURCE_DIR}/ccos_format_data.h + ${SOURCE_DIR}/ccos_format.h + ${SOURCE_DIR}/ccos_format.c ${SOURCE_DIR}/ccos_private.h ${SOURCE_DIR}/ccos_private.c ${SOURCE_DIR}/ccos_structure.h diff --git a/ccos_context.h b/ccos_context.h index 77260a1..89c0e7e 100644 --- a/ccos_context.h +++ b/ccos_context.h @@ -2,6 +2,7 @@ #define CCOS_CONTEXT_H #include +#include typedef struct { uint16_t sector_size; @@ -11,4 +12,12 @@ typedef struct { typedef const ccfs_context_t* ccfs_handle; +typedef struct { + uint16_t sector_size; + uint16_t superblock_id; + uint16_t bitmap_block_id; + size_t size; + uint8_t* data; +} ccos_disk_t; + #endif // CCOS_CONTEXT_H diff --git a/ccos_format.c b/ccos_format.c new file mode 100644 index 0000000..8f52b27 --- /dev/null +++ b/ccos_format.c @@ -0,0 +1,222 @@ +#include "ccos_format.h" +#include "ccos_format_data.h" + +#include "common.h" +#include "ccos_context.h" +#include "ccos_structure.h" +#include "ccos_private.h" + +#include +#include +#include +#include + +static uint8_t* new_empty_image(uint16_t sector_size, size_t bytes) { + uint8_t* image = calloc(bytes, sizeof(uint8_t)); + if (image == NULL) { + return NULL; + } + + const size_t sector_count = bytes / sector_size; + for (size_t i = 0; i < sector_count; i++) { + uint8_t* sector = image + (i * sector_size); + size_t marker_size = 4; + + memset(sector, 0xff, marker_size); + memset(sector + marker_size, 0x55, sector_size - marker_size); + } + + return image; +} + +static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk) { + const size_t sector_count = disk->size / disk->sector_size; + const size_t bitmask_required_bytes = sector_count / 8; + const size_t bitmask_bytes_per_sector = get_bitmask_size((ccfs_handle)disk); + const size_t bitmask_sectors = bitmask_required_bytes / bitmask_bytes_per_sector + 1; + + const size_t bitmask_tail_length = bitmask_bytes_per_sector - (bitmask_required_bytes % bitmask_bytes_per_sector); + const size_t bitmask_tail_offset = bitmask_required_bytes % bitmask_bytes_per_sector; + + // InitializeMedia~Run~ formats the bitmask based on values from the disk status. + // Since we are creating the disk ourselves, decided to place the bitmask in the sectors + // before the superblock. However, the bitmask can be placed anywhere.. + const size_t superblock_fid = disk->sector_size == 512 + ? DEFAULT_SUPERBLOCK + : DEFAULT_BUBBLE_SUPERBLOCK; + const size_t bitmask_fid = superblock_fid - bitmask_sectors; + + // Update disk structure with correct value. + disk->bitmap_block_id = bitmask_fid; + disk->superblock_id = bitmask_fid + bitmask_sectors; + + // Initialize empty bitmask. + for (size_t i = 0; i < bitmask_sectors; i++) { + const size_t sector_offset = (bitmask_fid + i) * disk->sector_size; + ccos_bitmask_t* bitmask = (ccos_bitmask_t*)&disk->data[sector_offset]; + + memset(bitmask, 0x00, disk->sector_size); + + bitmask->header.file_id = bitmask_fid; + bitmask->header.file_fragment_index = i; + bitmask->allocated = 0; + + if (i == bitmask_sectors - 1) { + uint8_t* bitmask_bytes = get_bitmask_bytes(bitmask); + memset(bitmask_bytes + bitmask_tail_offset, 0xff, bitmask_tail_length); + } + + update_bitmask_checksum((ccfs_handle)disk, bitmask); + } + + // Build list of bitmask blocks. + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks((ccfs_handle)disk, disk->data, disk->size); + + // Mark the bitmask blocks as used in the bitmask itself. + for (size_t i = 0; i < bitmask_sectors; i++) { + mark_block((ccfs_handle)disk, &bitmask_list, bitmask_fid + i, 1); + } + + return bitmask_list; +} + +static ccos_date_t get_current_date() { + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + struct tm* time_struct; + time_struct = localtime(&tp.tv_sec); + + return (ccos_date_t) { + .year = time_struct->tm_year + 1900, + .month = time_struct->tm_mon + 1, + .day = time_struct->tm_mday, + .hour = time_struct->tm_hour, + .minute = time_struct->tm_min, + .second = time_struct->tm_sec, + .tenthOfSec = tp.tv_nsec / 100000000, + .dayOfWeek = time_struct->tm_wday + 1, + .dayOfYear = time_struct->tm_yday + 1}; +} + +static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { + uint16_t id = disk->superblock_id; + + const size_t sector_offset = id * disk->sector_size; + ccos_inode_t* root_dir = (ccos_inode_t*)&disk->data[sector_offset]; + + memset(root_dir, 0x00, disk->sector_size); + + root_dir->header.file_id = id; + root_dir->header.file_fragment_index = 0; + + root_dir->desc.file_size = get_dir_default_size((ccfs_handle)disk); + + root_dir->desc.name_length = 0; + memset(root_dir->desc.name, ' ', sizeof(root_dir->desc.name)); + + root_dir->desc.creation_date = get_current_date(); + root_dir->desc.mod_date = root_dir->desc.creation_date; + root_dir->desc.expiration_date = (ccos_date_t) {}; + + root_dir->desc.dir_file_id = root_dir->header.file_id; + + root_dir->desc.protec = 1; + root_dir->desc.pswd_len = 5; + root_dir->desc.pswd[0] = '\x29'; + root_dir->desc.pswd[1] = '\xFF'; + root_dir->desc.pswd[2] = '\x47'; + root_dir->desc.pswd[3] = '\xC7'; + + root_dir->content_inode_info.header.file_id = id; + root_dir->content_inode_info.header.file_fragment_index = 0; + root_dir->content_inode_info.block_next = CCOS_INVALID_BLOCK; + root_dir->content_inode_info.block_current = id; + root_dir->content_inode_info.block_prev = CCOS_INVALID_BLOCK; + + mark_block((ccfs_handle)disk, bitmask_list, id, 1); + + uint16_t* content_blocks = get_inode_content_blocks(root_dir); + size_t max_content_blocks = get_inode_max_blocks((ccfs_handle)disk); + + memset(content_blocks, 0xFF, max_content_blocks * sizeof(uint16_t)); + + uint16_t superblock_entry_block = id + 1; + content_blocks[0] = superblock_entry_block; + + update_inode_checksums((ccfs_handle)disk, root_dir); + + ccos_block_header_t* superblock_entry = (ccos_block_header_t*)get_inode((ccfs_handle)disk, superblock_entry_block, disk->data); + memset(superblock_entry, 0x00, disk->sector_size); + superblock_entry->file_id = id; + superblock_entry->file_fragment_index = 0; + ((uint16_t*)superblock_entry)[2] = CCOS_DIR_LAST_ENTRY_MARKER; + + mark_block((ccfs_handle)disk, bitmask_list, superblock_entry_block, 1); +} + +static void write_boot_code(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { + // TODO: Support GRiDCase. + const uint8_t* boot_code = COMPASS_BOOT_CODE; + + size_t pages = sizeof(COMPASS_BOOT_CODE) / disk->sector_size; + size_t offset = sizeof(ZERO_PAGE) / disk->sector_size; + + for (size_t i = 0; i < pages; i++) { + memcpy(disk->data + (offset + i) * disk->sector_size, COMPASS_BOOT_CODE + i * disk->sector_size, disk->sector_size); + mark_block((ccfs_handle)disk, bitmask_list, offset + i, 1); + } +} + +static void write_zero_page(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { + size_t pages = sizeof(ZERO_PAGE) / disk->sector_size; + for (size_t i = 0; i < pages; i++) { + memcpy(disk->data + i * disk->sector_size, ZERO_PAGE + i * disk->sector_size, disk->sector_size); + mark_block((ccfs_handle)disk, bitmask_list, i, 1); + } +} + +static void write_blocks_numbers(ccos_disk_t* disk) { + // InitializeMedia~Run~ does not initialize these fields because it thinks the superblock + // will be located by the disk status. + // + // In our case, there is no real disk, so the sector numbers must be saved in the image itself. + *(uint16_t*)(disk->data + CCOS_SUPERBLOCK_ADDR_OFFSET) = disk->superblock_id; + *(uint16_t*)(disk->data + CCOS_BITMASK_ADDR_OFFSET) = disk->bitmap_block_id; +} + +int ccos_new_disk_image(uint16_t sector_size, size_t bytes, ccos_disk_t* output) { + if (sector_size != 256 && sector_size != 512) { + TRACE("Format image: invalid sector size"); + return EINVAL; + } + + if (bytes % sector_size != 0) { + TRACE("Format image: image size %zu is not a multiple of sector size %zu", bytes, sector_size); + return EINVAL; + } + + uint8_t* data = new_empty_image(sector_size, bytes); + if (data == NULL) { + return ENOMEM; + } + + ccos_disk_t disk = { + .sector_size = sector_size, + .superblock_id = 0, + .bitmap_block_id = 0, + .size = bytes, + .data = data + }; + + ccos_bitmask_list_t bitmask_list = init_bitmask(&disk); + write_superblock(&disk, &bitmask_list); + + write_boot_code(&disk, &bitmask_list); + + write_zero_page(&disk, &bitmask_list); + write_blocks_numbers(&disk); + + *output = disk; + + return 0; +} diff --git a/ccos_format.h b/ccos_format.h new file mode 100644 index 0000000..f7a5bc0 --- /dev/null +++ b/ccos_format.h @@ -0,0 +1,20 @@ +#ifndef CCOS_DISK_TOOL_CCOS_FORMAT_H +#define CCOS_DISK_TOOL_CCOS_FORMAT_H + +#include "ccos_context.h" + +#include +#include + +/** + * @brief Creates a new empty CCOS disk image. + * + * @param[in] sector_size The sector size in bytes. Supported values: 256 or 512. + * @param[in] bytes Total size of the image in bytes. Must be a multiple of sector_size. + * @param[out] output Disk image output. + * + * @return 0 on success, or an error code. + */ +int ccos_new_disk_image(uint16_t sector_size, size_t bytes, ccos_disk_t* output); + +#endif // CCOS_DISK_TOOL_CCOS_FORMAT_H diff --git a/ccos_format_data.h b/ccos_format_data.h new file mode 100644 index 0000000..2cedf73 --- /dev/null +++ b/ccos_format_data.h @@ -0,0 +1,173 @@ +#ifndef CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H +#define CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H + +#include +#include + +const uint8_t ZERO_PAGE[512] = { + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x21, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const uint8_t COMPASS_BOOT_CODE[2048] = { + 0x9A, 0x42, 0x07, 0x01, 0x20, 0x55, 0xB8, 0x80, 0x20, 0x8E, 0xD8, 0xBB, 0x08, 0x00, 0x58, 0x59, + 0x89, 0x0F, 0x89, 0x47, 0x02, 0xEB, 0xE9, 0x55, 0x43, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, + 0x6F, 0x6F, 0x74, 0x3A, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, + 0x72, 0x0D, 0x0A, 0x43, 0x43, 0x4F, 0x53, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x66, 0x6F, 0x75, 0x6E, + 0x64, 0x0D, 0x0A, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, + 0x72, 0x20, 0x69, 0x6E, 0x20, 0x43, 0x43, 0x4F, 0x53, 0x0D, 0x0A, 0x11, 0x50, 0x72, 0x6F, 0x67, + 0x72, 0x61, 0x6D, 0x73, 0x7E, 0x53, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x7E, 0x0C, 0x43, 0x43, + 0x4F, 0x53, 0x7E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x7E, 0x18, 0x53, 0x63, 0x72, 0x65, 0x65, + 0x6E, 0x2E, 0x49, 0x6E, 0x69, 0x74, 0x7E, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x49, 0x6D, 0x61, + 0x67, 0x65, 0x7E, 0x55, 0x80, 0x20, 0x00, 0x00, 0x40, 0x00, 0x55, 0x8B, 0xEC, 0xB8, 0x08, 0x00, + 0x0E, 0x50, 0xB8, 0x0D, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0x8B, 0x1E, 0x00, 0x00, 0x4B, + 0xD1, 0xE3, 0x2E, 0xFF, 0xA7, 0xA7, 0x00, 0xAD, 0x00, 0xB7, 0x00, 0xC1, 0x00, 0xB8, 0x15, 0x00, + 0x0E, 0x50, 0xB8, 0x0E, 0x00, 0xEB, 0x12, 0xB8, 0x23, 0x00, 0x0E, 0x50, 0xB8, 0x10, 0x00, 0xEB, + 0x08, 0xB8, 0x33, 0x00, 0x0E, 0x50, 0xB8, 0x18, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0xB8, + 0xE8, 0x03, 0x50, 0x9A, 0xD3, 0x00, 0xEF, 0xFF, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB0, 0x00, 0xBF, + 0x99, 0x0E, 0xB9, 0x13, 0x00, 0x1E, 0x07, 0xFC, 0xF2, 0xAA, 0xA0, 0xB0, 0x0E, 0xA2, 0xA7, 0x0E, + 0xC4, 0x46, 0x0A, 0xA3, 0x9B, 0x0E, 0x8C, 0x06, 0x9D, 0x0E, 0x8B, 0x46, 0x04, 0xA3, 0xA3, 0x0E, + 0x8B, 0x46, 0x06, 0x8B, 0x56, 0x08, 0xA3, 0x9F, 0x0E, 0x89, 0x16, 0xA1, 0x0E, 0x5D, 0xC2, 0x0A, + 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x04, 0x06, 0x50, 0x8B, 0x46, 0x08, 0xBA, 0x00, 0x00, 0x03, + 0x06, 0x0C, 0x00, 0x13, 0x16, 0x0E, 0x00, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0xAA, 0xFF, + 0xB8, 0x04, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x6C, 0x0A, 0x1E, 0x50, 0xFF, 0x1E, + 0xAC, 0x0E, 0xA1, 0x6C, 0x0A, 0x5D, 0xC2, 0x06, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, 0x04, 0x8D, + 0x47, 0x04, 0xA3, 0x72, 0x0A, 0x8C, 0x06, 0x74, 0x0A, 0xC4, 0x5E, 0x04, 0xB8, 0x00, 0x00, 0x26, + 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x87, 0x06, 0x04, 0x26, 0xC7, 0x07, 0x01, 0x00, 0x26, 0xC7, + 0x47, 0x02, 0x00, 0x00, 0xC4, 0x1E, 0x72, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, 0x6E, 0x0A, 0x8C, + 0x06, 0x70, 0x0A, 0x89, 0xC3, 0x8B, 0x4E, 0x08, 0x26, 0x89, 0x4F, 0x06, 0x5D, 0xC2, 0x06, 0x00, + 0x55, 0x8B, 0xEC, 0x83, 0x7E, 0x04, 0x00, 0x75, 0x08, 0xA1, 0x24, 0x00, 0x2D, 0xD4, 0x00, 0xEB, + 0x06, 0xA1, 0x24, 0x00, 0x83, 0xE8, 0x0C, 0xD1, 0xE8, 0x5D, 0xC2, 0x02, 0x00, 0x55, 0x8B, 0xEC, + 0xB8, 0x00, 0x00, 0x50, 0xE8, 0xD9, 0xFF, 0xA3, 0x76, 0x0A, 0xC4, 0x5E, 0x04, 0x8D, 0x4F, 0x04, + 0x89, 0x0E, 0x86, 0x0A, 0x8C, 0x06, 0x88, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x8B, 0x87, 0x04, 0x04, + 0x26, 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x24, 0x00, 0xBF, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x7B, + 0x20, 0xA3, 0x7A, 0x0A, 0x3B, 0x06, 0x76, 0x0A, 0x73, 0x0D, 0xA3, 0x7C, 0x0A, 0xC4, 0x1E, 0x86, + 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xEB, 0x1E, 0xA1, 0x7A, 0x0A, 0x2B, 0x06, 0x76, 0x0A, 0x50, 0xB9, + 0x01, 0x00, 0x51, 0xE8, 0x8A, 0xFF, 0x89, 0xC1, 0x58, 0x31, 0xD2, 0xF7, 0xF1, 0x89, 0x16, 0x7C, + 0x0A, 0xC4, 0x06, 0x86, 0x0A, 0xA3, 0x7E, 0x0A, 0x8C, 0x06, 0x80, 0x0A, 0x83, 0x3E, 0x7C, 0x0A, + 0x00, 0x75, 0x5A, 0xC4, 0x06, 0x7E, 0x0A, 0xA3, 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xA1, 0x76, + 0x0A, 0x3B, 0x06, 0x7A, 0x0A, 0x75, 0x0F, 0xC4, 0x1E, 0x86, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, + 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xC4, 0x1E, 0x82, 0x0A, 0x26, 0xFF, 0x77, 0x06, 0xC4, 0x5E, + 0x04, 0x8D, 0x47, 0x04, 0x06, 0x50, 0xE8, 0xB8, 0xFE, 0xA3, 0x78, 0x0A, 0x09, 0xC0, 0x75, 0x37, + 0x83, 0x3E, 0x7A, 0x0A, 0x00, 0x75, 0x16, 0xC4, 0x1E, 0x86, 0x0A, 0x26, 0x8B, 0x47, 0x04, 0x26, + 0x8B, 0x57, 0x06, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0x26, 0x89, 0x57, 0x02, 0x8B, 0x36, 0x7C, + 0x0A, 0xD1, 0xE6, 0xC4, 0x1E, 0x7E, 0x0A, 0x26, 0xFF, 0x70, 0x0C, 0xC4, 0x5E, 0x04, 0x8D, 0x87, + 0x04, 0x02, 0x06, 0x50, 0xE8, 0x7A, 0xFE, 0x5D, 0xC2, 0x04, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, + 0x0A, 0x8D, 0x87, 0x04, 0x02, 0xA3, 0x92, 0x0A, 0x8C, 0x06, 0x94, 0x0A, 0xC7, 0x06, 0x8E, 0x0A, + 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0x97, 0x06, 0x04, 0x26, + 0x3B, 0x57, 0x02, 0x75, 0x03, 0x26, 0x3B, 0x07, 0xB0, 0xFF, 0x74, 0x01, 0x40, 0xA2, 0xB1, 0x0E, + 0xA1, 0x8E, 0x0A, 0x3B, 0x46, 0x04, 0x72, 0x03, 0xE9, 0xE5, 0x00, 0xA0, 0xB1, 0x0E, 0xD0, 0xD8, + 0x73, 0x03, 0xE9, 0xDB, 0x00, 0x8B, 0x0E, 0x24, 0x00, 0xBA, 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, + 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0xBF, 0x06, 0x04, 0x87, 0xFA, 0x51, 0x57, 0x9A, 0x00, 0x00, + 0x7B, 0x20, 0x89, 0x3E, 0x8A, 0x0A, 0x5B, 0x58, 0x2B, 0xC7, 0xA3, 0x8C, 0x0A, 0x09, 0xFF, 0x75, + 0x0F, 0xC4, 0x46, 0x0A, 0x06, 0x50, 0xE8, 0x94, 0xFE, 0x09, 0xC0, 0x74, 0x03, 0xE9, 0xA0, 0x00, + 0x8B, 0x0E, 0x8C, 0x0A, 0xA1, 0x8E, 0x0A, 0x03, 0xC8, 0x8B, 0x46, 0x04, 0x3B, 0xC8, 0x76, 0x07, + 0x2B, 0x06, 0x8E, 0x0A, 0xA3, 0x8C, 0x0A, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, + 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x8C, 0x0A, 0xBF, 0x00, 0x00, 0x03, 0xC8, 0x13, 0xFA, 0x26, + 0x8B, 0x37, 0x26, 0x8B, 0x47, 0x02, 0x3B, 0xF8, 0x75, 0x02, 0x3B, 0xCE, 0x76, 0x15, 0x26, 0x2B, + 0xB7, 0x04, 0x04, 0x26, 0x1B, 0x87, 0x06, 0x04, 0x89, 0x36, 0x90, 0x0A, 0xC6, 0x06, 0xB1, 0x0E, + 0x01, 0xEB, 0x06, 0xA1, 0x8C, 0x0A, 0xA3, 0x90, 0x0A, 0xC4, 0x1E, 0x92, 0x0A, 0x8B, 0x36, 0x8A, + 0x0A, 0x8D, 0x70, 0x04, 0x06, 0xC4, 0x5E, 0x06, 0x8B, 0x3E, 0x8E, 0x0A, 0x8D, 0x39, 0x8B, 0x0E, + 0x90, 0x0A, 0x1E, 0x8E, 0x9E, 0xFE, 0xFF, 0xFC, 0xF2, 0xA4, 0x1F, 0x59, 0xA1, 0x90, 0x0A, 0x01, + 0x06, 0x8E, 0x0A, 0xC4, 0x5E, 0x0A, 0xBA, 0x00, 0x00, 0x26, 0x03, 0x87, 0x04, 0x04, 0x26, 0x13, + 0x97, 0x06, 0x04, 0x26, 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x97, 0x06, 0x04, 0xE9, 0x10, 0xFF, + 0xA1, 0x8E, 0x0A, 0x5D, 0xC2, 0x0A, 0x00, 0x55, 0x8B, 0xEC, 0xA1, 0x00, 0x00, 0x09, 0xC0, 0x75, + 0x2D, 0xFF, 0x76, 0x0C, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xE8, 0x6D, 0xFD, 0xB8, 0x58, 0x00, 0x1E, + 0x50, 0xB8, 0xEF, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0xAE, 0xFE, 0xA3, 0x98, 0x0A, + 0x09, 0xC0, 0x74, 0x07, 0x80, 0x3E, 0xEF, 0x0E, 0xFF, 0x75, 0x05, 0xB8, 0x02, 0x00, 0xEB, 0x6B, + 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0x96, 0x0A, 0x1E, 0x50, 0xB8, 0x02, 0x00, 0x50, 0xE8, 0x8A, + 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB2, 0x0E, 0x1E, 0x50, 0xB8, 0x01, + 0x00, 0x50, 0xE8, 0x76, 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB3, 0x0E, + 0x1E, 0x50, 0xA0, 0xB2, 0x0E, 0xB4, 0x00, 0x50, 0xE8, 0x60, 0xFE, 0xA3, 0x98, 0x0A, 0xC4, 0x5E, + 0x08, 0xA0, 0xB2, 0x0E, 0x26, 0x38, 0x07, 0x75, 0x26, 0xB9, 0xB3, 0x0E, 0x1E, 0x51, 0x8D, 0x4F, + 0x01, 0x06, 0x51, 0xB4, 0x00, 0x50, 0x9A, 0xEC, 0x00, 0xEF, 0xFF, 0xD0, 0xD8, 0x73, 0x10, 0xA1, + 0x96, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0xB8, 0x00, 0x00, 0x5D, 0xC2, 0x0A, 0x00, 0xB8, + 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xF0, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0x1B, 0xFE, + 0xA3, 0x98, 0x0A, 0xE9, 0x56, 0xFF, 0x55, 0x8B, 0xEC, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xB8, 0x18, + 0x00, 0x1E, 0x50, 0xB8, 0x0A, 0x00, 0x50, 0xE8, 0x01, 0xFE, 0xA3, 0x9C, 0x0A, 0xC7, 0x06, 0x9E, + 0x0A, 0x00, 0x00, 0xC7, 0x06, 0x9C, 0x0A, 0xEC, 0x03, 0xB8, 0xEC, 0x03, 0x39, 0x06, 0x9C, 0x0A, + 0x75, 0x1E, 0xB9, 0x60, 0x04, 0x1E, 0x51, 0xC4, 0x1E, 0x1A, 0x00, 0x8B, 0x36, 0x9E, 0x0A, 0x8D, + 0x08, 0x06, 0x51, 0x50, 0xE8, 0xD4, 0xFD, 0xA3, 0x9C, 0x0A, 0x01, 0x06, 0x9E, 0x0A, 0xEB, 0xD9, + 0xB8, 0x1A, 0x00, 0x1E, 0x50, 0xB8, 0x08, 0x00, 0x50, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x50, 0xC4, + 0x06, 0x1A, 0x00, 0x06, 0x50, 0xFF, 0x36, 0x9E, 0x0A, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x59, 0x03, + 0xC1, 0x3B, 0x06, 0x18, 0x00, 0x74, 0x06, 0xC7, 0x06, 0x00, 0x00, 0x03, 0x00, 0x5D, 0xC3, 0x55, + 0x8B, 0xEC, 0xB0, 0x00, 0xA2, 0x2F, 0x00, 0xA2, 0x56, 0x00, 0xA1, 0x76, 0x08, 0x09, 0xC0, 0x74, + 0x24, 0xA3, 0x50, 0x00, 0xA1, 0x78, 0x08, 0xA3, 0x52, 0x00, 0x8B, 0x0E, 0x7A, 0x08, 0x89, 0x0E, + 0x54, 0x00, 0x8A, 0x16, 0x7E, 0x08, 0x88, 0x16, 0x57, 0x00, 0xF7, 0xE1, 0xF7, 0x26, 0x7C, 0x08, + 0xA3, 0x26, 0x00, 0xEB, 0x17, 0xC7, 0x06, 0x52, 0x00, 0x09, 0x00, 0xC7, 0x06, 0x54, 0x00, 0x02, + 0x00, 0xC6, 0x06, 0x57, 0x00, 0x01, 0xC7, 0x06, 0x26, 0x00, 0xD0, 0x02, 0xB8, 0x22, 0x00, 0x1E, + 0x50, 0xB8, 0xFF, 0xFF, 0x89, 0xC2, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0x7B, 0xFB, 0xC6, + 0x06, 0xA5, 0x0E, 0x01, 0xB8, 0x05, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0xA0, 0x0A, + 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB8, 0x00, 0x00, 0x89, 0xC2, + 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xC6, 0x06, 0xF1, 0x0E, 0x01, 0xC6, 0x06, 0xB0, 0x0E, + 0x04, 0xBF, 0xEF, 0xFF, 0xB9, 0x24, 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0x80, + 0x3E, 0xB0, 0x0A, 0x62, 0x75, 0x18, 0xC6, 0x06, 0xB0, 0x0E, 0xFF, 0xBF, 0xEF, 0xFF, 0xB9, 0x1A, + 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0xA2, 0xF1, 0x0E, 0xEB, 0x1A, 0x80, 0x3E, + 0xB0, 0x0A, 0x63, 0x75, 0x07, 0xC6, 0x06, 0xB0, 0x0E, 0x06, 0xEB, 0x0C, 0x80, 0x3E, 0xB0, 0x0A, + 0x77, 0x74, 0x05, 0xC6, 0x06, 0xB0, 0x0E, 0x05, 0xB8, 0x22, 0x00, 0x1E, 0x50, 0xB8, 0x00, 0x00, + 0x89, 0xC2, 0x52, 0x50, 0xB8, 0x36, 0x00, 0x50, 0xE8, 0xEF, 0xFA, 0xB8, 0x01, 0x00, 0x50, 0xB8, + 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x00, 0x00, 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x83, 0x3E, 0x00, + 0x00, 0x00, 0x74, 0x02, 0x5D, 0xC3, 0xB8, 0x00, 0x02, 0x31, 0xD2, 0xF7, 0x36, 0x22, 0x00, 0xA3, + 0xA2, 0x0A, 0xB8, 0x68, 0x08, 0xA3, 0xA4, 0x0A, 0x8C, 0x1E, 0xA6, 0x0A, 0xC6, 0x06, 0xF2, 0x0E, + 0x00, 0xA1, 0xA2, 0x0A, 0x48, 0x8A, 0x0E, 0xF2, 0x0E, 0xB5, 0x00, 0x3B, 0xC8, 0x77, 0x29, 0x83, + 0x3E, 0x00, 0x00, 0x00, 0x75, 0x1C, 0xB8, 0x00, 0x00, 0x50, 0x8B, 0x16, 0x22, 0x00, 0x89, 0xD0, + 0xF7, 0xE1, 0x89, 0xC6, 0xC4, 0x1E, 0xA4, 0x0A, 0x8D, 0x00, 0x06, 0x50, 0xE8, 0xC2, 0xFA, 0xA3, + 0x00, 0x00, 0xFE, 0x06, 0xF2, 0x0E, 0x75, 0xC9, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x74, 0x02, 0x5D, + 0xC3, 0xA0, 0xF1, 0x0E, 0xD0, 0xD8, 0x73, 0x0B, 0x81, 0x3E, 0x26, 0x00, 0x40, 0x1F, 0x73, 0x03, + 0xE8, 0x8C, 0xFE, 0x81, 0x3E, 0x24, 0x0A, 0xAA, 0x55, 0x75, 0x1D, 0xA1, 0x08, 0x00, 0x8B, 0x16, + 0x0A, 0x00, 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xB8, 0x00, 0x00, 0x50, 0xB8, 0x68, 0x08, + 0x1E, 0x50, 0xE8, 0x7C, 0xFA, 0xA3, 0x00, 0x00, 0xA1, 0x88, 0x08, 0x09, 0xC0, 0x74, 0x03, 0xA3, + 0x2B, 0x00, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0x9A, 0x15, 0x00, 0xEF, 0xFF, 0x89, 0x1E, 0x14, 0x00, + 0x8C, 0x06, 0x16, 0x00, 0x26, 0x8A, 0x47, 0x16, 0xA2, 0xB0, 0x0A, 0xE8, 0xBA, 0xFE, 0xFF, 0x36, + 0x2B, 0x00, 0xB8, 0x4B, 0x00, 0x0E, 0x50, 0xB8, 0xAA, 0x0A, 0x1E, 0x50, 0xE8, 0xF8, 0xFC, 0xA3, + 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x5D, 0x00, 0x0E, 0x50, 0xB8, 0xAC, 0x0A, 0x1E, 0x50, + 0xE8, 0xE4, 0xFC, 0xA3, 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x6A, 0x00, 0x0E, 0x50, 0xB8, + 0xAE, 0x0A, 0x1E, 0x50, 0xE8, 0xD0, 0xFC, 0x09, 0xC0, 0x75, 0x22, 0xFF, 0x36, 0xAE, 0x0A, 0xB8, + 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x42, 0xFA, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0x2E, 0xC4, 0x06, 0x86, + 0x00, 0x06, 0x50, 0xB8, 0x80, 0x25, 0x50, 0xE8, 0x81, 0xFB, 0xA3, 0xA8, 0x0A, 0x83, 0x3E, 0x00, + 0x00, 0x00, 0x75, 0x18, 0xFF, 0x36, 0xAC, 0x0A, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x19, 0xFA, + 0xE8, 0x53, 0xFD, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x75, 0x02, 0x5D, 0xC3, 0xE8, 0x4B, 0xF9, 0xE9, + 0x79, 0xFF, 0x1E, 0x2E, 0x8E, 0x1E, 0x84, 0x00, 0x55, 0x8B, 0xEC, 0x89, 0xE0, 0xA3, 0x02, 0x00, + 0x8C, 0xD0, 0xA3, 0x04, 0x00, 0xB8, 0xB1, 0x0A, 0xA3, 0x10, 0x00, 0x8C, 0x1E, 0x12, 0x00, 0xFA, + 0xA1, 0x10, 0x00, 0x8B, 0x16, 0x12, 0x00, 0x05, 0xE8, 0x03, 0x83, 0xE8, 0x0A, 0x89, 0xC4, 0xA1, + 0x12, 0x00, 0x8E, 0xD0, 0xFB, 0xE8, 0x2C, 0xFF, 0xFA, 0xA1, 0x02, 0x00, 0x89, 0xC4, 0xA1, 0x04, + 0x00, 0x8E, 0xD0, 0xFB, 0xFF, 0x36, 0x0E, 0x00, 0xFF, 0x36, 0x0C, 0x00, 0xB8, 0x01, 0x00, 0x50, + 0xB8, 0x21, 0x43, 0x50, 0xFF, 0x1E, 0x1E, 0x00, 0x5D, 0x1F, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x0B, 0xFF, 0x75, 0x1D, 0x3B, 0xCA, 0x76, 0x09, 0xF7, 0xF1, 0x33, 0xF6, 0x8B, 0xFA, 0x33, 0xD2, + 0xCB, 0x8B, 0xF8, 0x8B, 0xC2, 0x33, 0xD2, 0xF7, 0xF1, 0x97, 0xF7, 0xF1, 0x87, 0xD7, 0x33, 0xF6, + 0xCB, 0x55, 0x8B, 0xE9, 0x8B, 0xDF, 0x33, 0xF6, 0x8B, 0xFE, 0xB9, 0x20, 0x00, 0xD1, 0xE7, 0xD1, + 0xD6, 0xD1, 0xE0, 0xD1, 0xD2, 0x83, 0xD7, 0x00, 0x2B, 0xFD, 0x1B, 0xF3, 0x40, 0x73, 0x05, 0x03, + 0xFD, 0x13, 0xF3, 0x48, 0xE2, 0xE7, 0x5D, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x76, 0x65, +}; + +#endif // CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H diff --git a/ccos_image.c b/ccos_image.c index 96c8561..83dc5da 100644 --- a/ccos_image.c +++ b/ccos_image.c @@ -695,22 +695,3 @@ int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, cc return 0; } - -uint8_t* ccos_create_new_image(ccfs_handle ctx, size_t blocks) { - size_t block_size = get_block_size(ctx); - size_t image_size = block_size * blocks; - - uint8_t* data = malloc(image_size); - if (data == NULL) { - fprintf(stderr, "Unable to create new image: unable to allocate memory: %s!\n", strerror(errno)); - return NULL; - } - - if (format_image(ctx, data, image_size) == -1) { - fprintf(stderr, "Unable to create new image: unable to format image!\n"); - free(data); - return NULL; - } - - return data; -} diff --git a/ccos_image.h b/ccos_image.h index ec1a4ff..a79abb3 100644 --- a/ccos_image.h +++ b/ccos_image.h @@ -2,6 +2,7 @@ #define CCOS_IMAGE_H #include "ccos_structure.h" +#include "ccos_format.h" #include "string_utils.h" typedef struct { @@ -358,14 +359,4 @@ char* ccos_get_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size); */ int ccos_set_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size, const char* label); -/** - * @brief Create new empty image. - * - * @param[in] ctx Filesystem context handle. - * @param[in] blocks Number of blocks in the image. - * - * @return Image data on success, NULL otherwise. - */ -uint8_t* ccos_create_new_image(ccfs_handle ctx, size_t blocks); - #endif // CCOS_IMAGE_H diff --git a/ccos_private.c b/ccos_private.c index a7dc3c0..3060ba8 100644 --- a/ccos_private.c +++ b/ccos_private.c @@ -1,6 +1,7 @@ // // Created by kirill on 21.05.2020. // +#include "ccos_structure.h" #include "common.h" #include "ccos_image.h" #include "ccos_private.h" @@ -11,9 +12,6 @@ #include #include -#define CCOS_SUPERBLOCK_ADDR_OFFSET 0x20 -#define CCOS_BITMASK_ADDR_OFFSET 0x1E - #define CCOS_CONTENT_BLOCKS_END_MARKER 0xFFFF uint16_t calc_checksum(const uint8_t* data, uint16_t data_size) { @@ -35,10 +33,10 @@ uint16_t calc_inode_metadata_checksum(const ccos_inode_t* inode) { } uint16_t calc_inode_blocks_checksum(ccfs_handle ctx, const ccos_inode_t* inode) { - const size_t start_offset = offsetof(ccos_inode_t, content_inode_info) + offsetof(ccos_block_data_t, block_next); - const uint8_t* checksum_data = (const uint8_t*)&inode->content_inode_info.block_next; - uint16_t checksum_data_size = get_block_size(ctx) - start_offset; + uint16_t checksum_data_size = get_log_block_size(ctx) + - sizeof(ccos_inode_desc_t) + - offsetof(ccos_block_data_t, block_next); uint16_t blocks_checksum = calc_checksum(checksum_data, checksum_data_size); blocks_checksum += inode->content_inode_info.header.file_id; @@ -207,7 +205,8 @@ static ccos_bitmask_t* get_bitmask(ccfs_handle ctx, uint8_t* data, size_t data_s size_t block_size = get_block_size(ctx); uint16_t bitmask_block = *((uint16_t*)&(data[CCOS_BITMASK_ADDR_OFFSET])); - if (bitmask_block == 0) bitmask_block = ctx->bitmap_block_id; + // FIXME: always use values from ctx->bitmap_block_id. + if (bitmask_block == 0 || bitmask_block == 0x5555) bitmask_block = ctx->bitmap_block_id; uint32_t blocks_in_image = data_size / block_size; if (bitmask_block > blocks_in_image) { @@ -1016,101 +1015,3 @@ int change_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date, date_ update_inode_checksums(ctx, file); return 0; } - -int format_image(ccfs_handle ctx, uint8_t* data, size_t image_size) { - size_t block_size = get_block_size(ctx); - size_t bitmask_size = get_bitmask_size(ctx); - - uint16_t superblock = ctx->superblock_id; - - size_t sb_offset = block_size * superblock; - if (sb_offset >= image_size) { - fprintf(stderr, "Unable to format image: image_size < superblock offset!\n"); - return -1; - } - - // Set superblock - uint16_t* sb_offset_addr = ((uint16_t*)&(data[CCOS_SUPERBLOCK_ADDR_OFFSET])); - *sb_offset_addr = superblock; - - uint16_t* sb_addr = ((uint16_t*)&(data[sb_offset])); - *sb_addr = superblock; - - // Create bitmask - size_t free_blocks = image_size / block_size; - size_t free_bitmask_count = free_blocks / 8; - // How many bitmask blocks we need for the given image size? - size_t bitmask_blocks_count = (free_bitmask_count + bitmask_size - 1) / bitmask_size; - // How many blocks we mark as free at the last bitmask block? - size_t free_bitmask_remainder = bitmask_size - (bitmask_blocks_count * bitmask_size - free_bitmask_count); - uint16_t bitmask_file_id = superblock - bitmask_blocks_count; - - uint16_t* bitmask_offset_addr = (uint16_t*)&(data[CCOS_BITMASK_ADDR_OFFSET]); - *bitmask_offset_addr = bitmask_file_id; - - for (size_t i = bitmask_blocks_count; i > 0; i--) { - uint16_t bitmask_block = superblock - i; - ccos_bitmask_t* bitmask = (ccos_bitmask_t*)&(data[bitmask_block * block_size]); - bitmask->header.file_id = bitmask_file_id; - bitmask->header.file_fragment_index = bitmask_blocks_count - i; - - uint8_t* bitmask_bytes = get_bitmask_bytes(bitmask); - if (i == 1) { - // last block - memset(bitmask_bytes, 0, free_bitmask_remainder); - memset(bitmask_bytes + free_bitmask_remainder, 0xFF, bitmask_size - free_bitmask_remainder); - } else { - memset(bitmask_bytes, 0, bitmask_size); - } - } - - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(ctx, data, image_size); - for (size_t j = bitmask_blocks_count; j > 0; j--) { - mark_block(ctx, &bitmask_list, superblock - j, 1); // mark bitmask blocks as used - } - mark_block(ctx, &bitmask_list, superblock, 1); // superblock - mark_block(ctx, &bitmask_list, superblock + 1, 1); // superblock contents - - // Format root directory - ccos_inode_t* root_dir = (ccos_inode_t*)sb_addr; - root_dir->header.file_id = superblock; - root_dir->header.file_fragment_index = 0; - - // Root directory is it's own parent - root_dir->desc.dir_file_id = root_dir->header.file_id; - root_dir->desc.file_size = get_dir_default_size(ctx); - - // Same as in GRiD-OS formatted blank image - root_dir->desc.protec = 0x1; - root_dir->desc.pswd_len = 0x5; - root_dir->desc.pswd[0] = '\x29'; - root_dir->desc.pswd[1] = '\xFF'; - root_dir->desc.pswd[2] = '\x47'; - root_dir->desc.pswd[3] = '\xC7'; - - // Fill root directory contents - root_dir->content_inode_info.header.file_id = superblock; - root_dir->content_inode_info.header.file_fragment_index = 0; - root_dir->content_inode_info.block_next = CCOS_INVALID_BLOCK; - root_dir->content_inode_info.block_current = superblock; - root_dir->content_inode_info.block_prev = CCOS_INVALID_BLOCK; - - // Fill content blocks - uint16_t* content_blocks = get_inode_content_blocks(root_dir); - size_t max_content_blocks = get_inode_max_blocks(ctx); - - memset(content_blocks, 0xFF, max_content_blocks * sizeof(uint16_t)); - - uint16_t superblock_entry_block = superblock + 1; - content_blocks[0] = superblock_entry_block; - - update_inode_checksums(ctx, root_dir); - - // Root directory contents - ccos_block_header_t* superblock_entry = (ccos_block_header_t*)get_inode(ctx, superblock_entry_block, data); - superblock_entry->file_id = superblock; - superblock_entry->file_fragment_index = 0; - ((uint16_t*)superblock_entry)[2] = CCOS_DIR_LAST_ENTRY_MARKER; - - return 0; -} diff --git a/ccos_private.h b/ccos_private.h index 665a032..b378047 100644 --- a/ccos_private.h +++ b/ccos_private.h @@ -9,6 +9,14 @@ #include "ccos_structure.h" #include "string_utils.h" +#define DEFAULT_SUPERBLOCK 0x121 +#define DEFAULT_BUBBLE_SUPERBLOCK 0x3fe +#define CCOS_SUPERBLOCK_ADDR_OFFSET 0x20 + +#define DEFAULT_BITMASK_BLOCK_ID (DEFAULT_SUPERBLOCK - 1) +#define DEFAULT_BUBBLE_BITMASK_BLOCK_ID (DEFAULT_BUBBLE_SUPERBLOCK - 1) +#define CCOS_BITMASK_ADDR_OFFSET 0x1E + typedef struct { uint16_t offset; size_t size; @@ -383,15 +391,4 @@ int is_root_dir(const ccos_inode_t* file); */ int change_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date, date_type_t type); -/** - * @brief Create CCOS filesystem in the given image. - * - * @param[in] ctx Filesystem context handle. - * @param data CCOS image data. - * @param[in] image_size Image size. - * - * @return 0 on success, -1 otherwise. - */ -int format_image(ccfs_handle ctx, uint8_t* data, size_t image_size); - #endif // CCOS_DISK_TOOL_CCOS_PRIVATE_H diff --git a/main.c b/main.c index c4e0cce..10cffc9 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include "common.h" #include "ccos_context.h" +#include "ccos_private.h" #include "ccos_image.h" #include "wrapper.h" @@ -15,8 +16,6 @@ #define SUPERBLOCK_OPT 2001 #define DEFAULT_SECTOR_SIZE 512 -#define DEFAULT_SUPERBLOCK 0x121 -#define DEFAULT_BITMAP_BLOCK (DEFAULT_SUPERBLOCK - 1) typedef enum { @@ -100,7 +99,7 @@ ccfs_context_t* default_ccos_context() { ctx->sector_size = DEFAULT_SECTOR_SIZE; ctx->superblock_id = DEFAULT_SUPERBLOCK; - ctx->bitmap_block_id = DEFAULT_BITMAP_BLOCK; + ctx->bitmap_block_id = DEFAULT_BITMASK_BLOCK_ID; return ctx; } diff --git a/wrapper.c b/wrapper.c index 30a7655..d9c1667 100644 --- a/wrapper.c +++ b/wrapper.c @@ -8,6 +8,8 @@ #include #include #include +#include "ccos_context.h" +#include "ccos_format.h" #define PROGRAMS_DIR_1 "Programs~Subject~" #define PROGRAMS_DIR_2 "Programs~subject~" @@ -831,21 +833,23 @@ int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, ui int create_blank_image(ccfs_handle ctx, char* path, size_t size) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); - return -1; + return EINVAL; } if (size % ctx->sector_size != 0) { fprintf(stderr, "Image size must be a multiple of the sector size %d\n", ctx->sector_size); - return -1; + return EINVAL; } - uint8_t* image_data = ccos_create_new_image(ctx, size / ctx->sector_size); - if (image_data == NULL) { - fprintf(stderr, "Unable to create blank image!\n"); - return -1; + ccos_disk_t disk; + + int res = ccos_new_disk_image(ctx->sector_size, size, &disk); + if (res) { + fprintf(stderr, "Failed to create new disk image. Error code: %s\n", strerror(res)); + return res; } - int res = save_image(path, image_data, size, 1); - free(image_data); + res = save_image(path, disk.data, disk.size, 1); + free(disk.data); return res; } From 97f940af847acc67a9b0c6f18d93b8003b79b750 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 02:33:09 +0100 Subject: [PATCH 05/13] select superblock based on disk size --- ccos_format.c | 119 ++++++++++++++++++++++++++++++++----------------- ccos_private.h | 1 + 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/ccos_format.c b/ccos_format.c index 8f52b27..e47047f 100644 --- a/ccos_format.c +++ b/ccos_format.c @@ -6,18 +6,26 @@ #include "ccos_structure.h" #include "ccos_private.h" +#include #include #include #include #include -static uint8_t* new_empty_image(uint16_t sector_size, size_t bytes) { - uint8_t* image = calloc(bytes, sizeof(uint8_t)); +typedef struct { + uint16_t sector; + uint16_t count; + uint16_t tail_length; + uint16_t tail_offset; +} bitmask_info_t; + +static uint8_t* new_empty_image(uint16_t sector_size, size_t disk_size) { + uint8_t* image = calloc(disk_size, sizeof(uint8_t)); if (image == NULL) { return NULL; } - const size_t sector_count = bytes / sector_size; + const size_t sector_count = disk_size / sector_size; for (size_t i = 0; i < sector_count; i++) { uint8_t* sector = image + (i * sector_size); size_t marker_size = 4; @@ -29,41 +37,67 @@ static uint8_t* new_empty_image(uint16_t sector_size, size_t bytes) { return image; } -static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk) { - const size_t sector_count = disk->size / disk->sector_size; - const size_t bitmask_required_bytes = sector_count / 8; - const size_t bitmask_bytes_per_sector = get_bitmask_size((ccfs_handle)disk); - const size_t bitmask_sectors = bitmask_required_bytes / bitmask_bytes_per_sector + 1; +static uint16_t select_superblock(uint16_t sector_size, size_t disk_size) { + assert(sector_size == 256 || sector_size == 512); + + if (sector_size == 256) { + // For bubble disks we always use the default value. + return DEFAULT_BUBBLE_SUPERBLOCK; + } else if (disk_size < 1 * 1024 * 1024) { + // For floppy disks we always use the block number from the 2102 floppy firmware. + return DEFAULT_SUPERBLOCK; + } else if (disk_size < 4 * 1024 * 1024) { + // Value selected by analogy. + return 0x510; + } else if (disk_size < 10 * 1024 * 1024) { + // Value selected by analogy. + return 0x1010; + } else { + // For big hard drives we always use the block number from the 2101 hard disk firmware. + return DEFAULT_HDD_SUPERBLOCK; + } +} + +static bitmask_info_t calculate_bitmask_info(uint16_t sector_size, size_t disk_size) { + assert(sector_size == 256 || sector_size == 512); + + const uint16_t superblock = select_superblock(sector_size, disk_size); + + // Calculate bitmask. + const uint16_t sector_count = disk_size / sector_size; + const uint16_t required_bytes = sector_count / 8; + const uint16_t bytes_per_sector = sector_size == 512 ? BS512_BITMASK_SIZE : BS256_BITMASK_SIZE; + const uint16_t count = required_bytes / bytes_per_sector + 1; - const size_t bitmask_tail_length = bitmask_bytes_per_sector - (bitmask_required_bytes % bitmask_bytes_per_sector); - const size_t bitmask_tail_offset = bitmask_required_bytes % bitmask_bytes_per_sector; + const uint16_t bitmask = superblock - count; - // InitializeMedia~Run~ formats the bitmask based on values from the disk status. - // Since we are creating the disk ourselves, decided to place the bitmask in the sectors - // before the superblock. However, the bitmask can be placed anywhere.. - const size_t superblock_fid = disk->sector_size == 512 - ? DEFAULT_SUPERBLOCK - : DEFAULT_BUBBLE_SUPERBLOCK; - const size_t bitmask_fid = superblock_fid - bitmask_sectors; + const uint16_t tail_length = bytes_per_sector - (required_bytes % bytes_per_sector); + const uint16_t tail_offset = required_bytes % bytes_per_sector; - // Update disk structure with correct value. - disk->bitmap_block_id = bitmask_fid; - disk->superblock_id = bitmask_fid + bitmask_sectors; + // Combine and return. + return (bitmask_info_t) { + .sector = bitmask, + .count = count, + .tail_length = tail_length, + .tail_offset = tail_offset, + }; +} +static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk, bitmask_info_t info) { // Initialize empty bitmask. - for (size_t i = 0; i < bitmask_sectors; i++) { - const size_t sector_offset = (bitmask_fid + i) * disk->sector_size; + for (size_t i = 0; i < info.count; i++) { + const size_t sector_offset = (info.sector + i) * disk->sector_size; ccos_bitmask_t* bitmask = (ccos_bitmask_t*)&disk->data[sector_offset]; memset(bitmask, 0x00, disk->sector_size); - bitmask->header.file_id = bitmask_fid; + bitmask->header.file_id = info.sector; bitmask->header.file_fragment_index = i; bitmask->allocated = 0; - if (i == bitmask_sectors - 1) { + if (i == info.count - 1) { uint8_t* bitmask_bytes = get_bitmask_bytes(bitmask); - memset(bitmask_bytes + bitmask_tail_offset, 0xff, bitmask_tail_length); + memset(bitmask_bytes + info.tail_offset, 0xff, info.tail_length); } update_bitmask_checksum((ccfs_handle)disk, bitmask); @@ -73,8 +107,8 @@ static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk) { ccos_bitmask_list_t bitmask_list = find_bitmask_blocks((ccfs_handle)disk, disk->data, disk->size); // Mark the bitmask blocks as used in the bitmask itself. - for (size_t i = 0; i < bitmask_sectors; i++) { - mark_block((ccfs_handle)disk, &bitmask_list, bitmask_fid + i, 1); + for (size_t i = 0; i < info.count; i++) { + mark_block((ccfs_handle)disk, &bitmask_list, info.sector + i, 1); } return bitmask_list; @@ -173,48 +207,49 @@ static void write_zero_page(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list memcpy(disk->data + i * disk->sector_size, ZERO_PAGE + i * disk->sector_size, disk->sector_size); mark_block((ccfs_handle)disk, bitmask_list, i, 1); } -} -static void write_blocks_numbers(ccos_disk_t* disk) { - // InitializeMedia~Run~ does not initialize these fields because it thinks the superblock - // will be located by the disk status. + // InitializeMedia~Run~ in GRiD-OS 3.1.0 does not initialize these fields + // because it thinks the superblock will be located by the disk status. // // In our case, there is no real disk, so the sector numbers must be saved in the image itself. *(uint16_t*)(disk->data + CCOS_SUPERBLOCK_ADDR_OFFSET) = disk->superblock_id; *(uint16_t*)(disk->data + CCOS_BITMASK_ADDR_OFFSET) = disk->bitmap_block_id; } -int ccos_new_disk_image(uint16_t sector_size, size_t bytes, ccos_disk_t* output) { +int ccos_new_disk_image(uint16_t sector_size, size_t disk_size, ccos_disk_t* output) { if (sector_size != 256 && sector_size != 512) { TRACE("Format image: invalid sector size"); return EINVAL; } - if (bytes % sector_size != 0) { - TRACE("Format image: image size %zu is not a multiple of sector size %zu", bytes, sector_size); + if (disk_size % sector_size != 0) { + TRACE("Format image: image size %zu is not a multiple of sector size %zu", disk_size, sector_size); return EINVAL; } - uint8_t* data = new_empty_image(sector_size, bytes); + uint8_t* data = new_empty_image(sector_size, disk_size); if (data == NULL) { return ENOMEM; } + // InitializeMedia~Run~ gets the block numbers from the disk status. + // In the 2101 and 2102 firmwares, the bitmask and superblock numbers are hardcoded. + // Because we create disk images ourselves, we can choose any values and save them inside the image. + const uint16_t superblock = select_superblock(sector_size, disk_size); + const bitmask_info_t bitmask = calculate_bitmask_info(sector_size, disk_size); + ccos_disk_t disk = { .sector_size = sector_size, - .superblock_id = 0, - .bitmap_block_id = 0, - .size = bytes, + .superblock_id = superblock, + .bitmap_block_id = bitmask.sector, + .size = disk_size, .data = data }; - ccos_bitmask_list_t bitmask_list = init_bitmask(&disk); + ccos_bitmask_list_t bitmask_list = init_bitmask(&disk, bitmask); write_superblock(&disk, &bitmask_list); - write_boot_code(&disk, &bitmask_list); - write_zero_page(&disk, &bitmask_list); - write_blocks_numbers(&disk); *output = disk; diff --git a/ccos_private.h b/ccos_private.h index b378047..2b006af 100644 --- a/ccos_private.h +++ b/ccos_private.h @@ -10,6 +10,7 @@ #include "string_utils.h" #define DEFAULT_SUPERBLOCK 0x121 +#define DEFAULT_HDD_SUPERBLOCK 0x2420 #define DEFAULT_BUBBLE_SUPERBLOCK 0x3fe #define CCOS_SUPERBLOCK_ADDR_OFFSET 0x20 From b8bfa645e5f516c4db51f3280625949b5a8f69ca Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 04:11:27 +0100 Subject: [PATCH 06/13] add tests for 360kb and 720kb floppies --- tests/CMakeLists.txt | 5 +- tests/CTestLibfaketime.cmake | 44 ++++++++ tests/files/floppy 360k/empty.img | Bin 0 -> 368640 bytes tests/files/floppy 720k/empty.img | Bin 0 -> 737280 bytes tests/format_test.c | 177 ++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 tests/CTestLibfaketime.cmake create mode 100644 tests/files/floppy 360k/empty.img create mode 100644 tests/files/floppy 720k/empty.img create mode 100644 tests/format_test.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 507e0c8..1d94a35 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,8 +2,11 @@ find_package(Criterion REQUIRED) add_executable(ccos_tests ${CMAKE_CURRENT_LIST_DIR}/api_test.c + ${CMAKE_CURRENT_LIST_DIR}/format_test.c ) target_link_libraries(ccos_tests PRIVATE ccos_api Criterion::Criterion) -add_test(NAME ccos_tests COMMAND ccos_tests) +add_test(NAME ccos_tests COMMAND ccos_tests WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) + +include(${CMAKE_CURRENT_LIST_DIR}/CTestLibfaketime.cmake) diff --git a/tests/CTestLibfaketime.cmake b/tests/CTestLibfaketime.cmake new file mode 100644 index 0000000..cbefe4a --- /dev/null +++ b/tests/CTestLibfaketime.cmake @@ -0,0 +1,44 @@ +set(CCOS_FAKETIME "1985-09-26 13:31:01.800" CACHE STRING "Fake wall-clock time injected into tests via libfaketime (FAKETIME env var)") +set(CCOS_FAKETIME_LIB "" CACHE FILEPATH "Absolute path to libfaketime library used for preloading (overrides auto-detection)") + +if(APPLE) + # macOS uses DYLD_* interposing instead of LD_PRELOAD. + # We must use an absolute path; a bare 'libfaketime.dylib' typically won't be found by dyld. + # If auto-detection fails, set it explicitly: -DCCOS_FAKETIME_LIB=/path/to/libfaketime.1.dylib + if(CCOS_FAKETIME_LIB STREQUAL "") + find_library(_ccos_faketime_lib + # find_library() adds 'lib' prefix and platform suffixes automatically, + # so use names without the 'lib' prefix. + NAMES faketime.1 faketime + PATHS + /opt/homebrew/opt/libfaketime/lib/faketime + /opt/homebrew/lib/faketime + /opt/homebrew/lib + /usr/local/lib/faketime + /usr/local/lib + ) + if(NOT _ccos_faketime_lib) + message(FATAL_ERROR "libfaketime not found. Set -DCCOS_FAKETIME_LIB=/absolute/path/to/libfaketime.1.dylib") + endif() + set(CCOS_FAKETIME_LIB "${_ccos_faketime_lib}" CACHE FILEPATH "Absolute path to libfaketime library used for preloading (overrides auto-detection)" FORCE) + endif() + set_tests_properties(ccos_tests PROPERTIES ENVIRONMENT + "FAKETIME=${CCOS_FAKETIME};DYLD_INSERT_LIBRARIES=${CCOS_FAKETIME_LIB};DYLD_FORCE_FLAT_NAMESPACE=1" + ) +elseif(UNIX) + # Linux/BSD typically use LD_PRELOAD. + # If auto-detection fails, set it explicitly: -DCCOS_FAKETIME_LIB=/path/to/libfaketime.so.1 + if(CCOS_FAKETIME_LIB STREQUAL "") + find_library(_ccos_faketime_lib + NAMES faketime.so.1 faketime + ) + if(NOT _ccos_faketime_lib) + message(FATAL_ERROR "libfaketime not found. Set -DCCOS_FAKETIME_LIB=/absolute/path/to/libfaketime.so.1") + endif() + set(CCOS_FAKETIME_LIB "${_ccos_faketime_lib}" CACHE FILEPATH "Absolute path to libfaketime library used for preloading (overrides auto-detection)" FORCE) + endif() + set_tests_properties(ccos_tests PROPERTIES ENVIRONMENT + "FAKETIME=${CCOS_FAKETIME};LD_PRELOAD=${CCOS_FAKETIME_LIB}" + ) +endif() + diff --git a/tests/files/floppy 360k/empty.img b/tests/files/floppy 360k/empty.img new file mode 100644 index 0000000000000000000000000000000000000000..9574bfb944a8c0d2ae12a8d542899059b7e6a0b9 GIT binary patch literal 368640 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 z-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBB zvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2; zz@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC z-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQt zZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^ zYD|Bm z*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6 z-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq z_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3 zZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{ zHog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3 z?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W z2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl z)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh z{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0| zKidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO-~Ma^YD|Bm*#_A3?%)1w z18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBBvkkE6-M{_W2H5oO z-~Ma^YD|Bm*#_A3?%)1w18jQtZ-2G{Hog0|KidGC-u>I3ZGcVh{_W2;z@~Tq_GcSl)4PBB zvkkE6-M{_W2H5oO-~Ma^Y + +#include + +#include +#include +#include +#include +#include +#include +#include "ccos_context.h" +#include "ccos_format.h" + +static void display_bad_sector(const uint8_t* actual, size_t sector_size) { + for (size_t i = 0; i < sector_size; i += 16) { + char line[128]; + snprintf(line, sizeof(line), "%03zu | ", i); + + for (size_t j = 0; j < 16; ++j) { + char hex[5]; + snprintf(hex, sizeof(hex), " %02X", actual[i + j]); + strncat(line, hex, sizeof(line) - strlen(line) - 1); + } + + cr_log_error("%s", line); + } +} + +static void compare_disk_with_ref(const ccos_disk_t* disk, const uint8_t* expected) { + const size_t sector_count = disk->size / disk->sector_size; + + for (size_t i = 0; i < sector_count; i++) { + const uint8_t* actual_sector = disk->data + i * disk->sector_size; + const uint8_t* expected_sector = expected + i * disk->sector_size; + + if (memcmp(actual_sector, expected_sector, disk->sector_size)) { + cr_log_error("Sector %zu mismatch", i); + + cr_log_error("Actual sector:"); + display_bad_sector(actual_sector, disk->sector_size); + + cr_log_error("Expected sector:"); + display_bad_sector(expected_sector, disk->sector_size); + + cr_assert(!"Bad sector"); + } + } +} + +static uint8_t* load_image(const char* path, size_t expected_size) { + FILE* f = fopen(path, "rb"); + if (f == NULL) { + cr_log_error("Failed to open file '%s'", path); + return NULL; + } + + uint8_t* data = malloc(expected_size); + if (data == NULL) { + cr_log_error("Failed to allocate %zu bytes for loading '%s'", expected_size, path); + fclose(f); + return NULL; + } + + size_t read = fread(data, 1, expected_size, f); + fclose(f); + + if (read != expected_size) { + cr_log_error("Read %zu bytes, expected %zu from '%s'", read, expected_size, path); + free(data); + return NULL; + } + + return data; +} + +// Test(format, bubbles) { +// size_t image_size = 3 * 128 * 1024; + +// ccos_disk_t disk; + +// int ret = ccos_new_disk_image(256, image_size, &disk); +// cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); + +// uint8_t* expected = load_image("files/bubbles/empty.img", image_size); +// cr_assert_not_null(expected, "Failed to load expected image"); + +// compare_disk_with_ref(&disk, expected); + +// free(disk.data); +// free(expected); +// } + +Test(format, floppy_360k) { + size_t image_size = 360 * 1024; + + ccos_disk_t disk; + + int ret = ccos_new_disk_image(512, image_size, &disk); + cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); + + uint8_t* expected = load_image("files/floppy 360k/empty.img", image_size); + cr_assert_not_null(expected, "Failed to load expected image"); + + compare_disk_with_ref(&disk, expected); + + free(disk.data); + free(expected); +} + +Test(format, floppy_720k) { + size_t image_size = 720 * 1024; + + ccos_disk_t disk; + + int ret = ccos_new_disk_image(512, image_size, &disk); + cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); + + uint8_t* expected = load_image("files/floppy 720k/empty.img", image_size); + cr_assert_not_null(expected, "Failed to load expected image"); + + compare_disk_with_ref(&disk, expected); + + free(disk.data); + free(expected); +} + +// Test(format, hdd_10mb) { +// ccfs_context_t ctx = { +// .sector_size = 512, +// .superblock_id = 0x121, +// .bitmap_block_id = 0x120, +// }; + +// size_t image_size = 10 * 1024 * 1024; + +// uint8_t* buffer = calloc(1, image_size); +// cr_assert_not_null(buffer, "Failed to allocate buffer"); + +// int result = format_image(&ctx, buffer, image_size); +// cr_assert_eq(result, 0, "format_image failed"); + +// uint8_t* expected = load_image("files/hdd 10mb/empty.img", image_size); +// cr_assert_not_null(expected, "Failed to load expected image"); + +// compare_images_sector_by_sector(buffer, expected, image_size, ctx.sector_size); + +// free(buffer); +// free(expected); +// } + +// Test(format, hdd_20mb) { +// ccfs_context_t ctx = { +// .sector_size = 512, +// .superblock_id = 0x121, +// .bitmap_block_id = 0x120, +// }; + +// size_t image_size = 20 * 1024 * 1024; + +// uint8_t* buffer = calloc(1, image_size); +// cr_assert_not_null(buffer, "Failed to allocate buffer"); + +// int result = format_image(&ctx, buffer, image_size); +// cr_assert_eq(result, 0, "format_image failed"); + +// uint8_t* expected = load_image("files/hdd 20mb/empty.img", image_size); +// cr_assert_not_null(expected, "Failed to load expected image"); + +// compare_images_sector_by_sector(buffer, expected, image_size, ctx.sector_size); + +// free(buffer); +// free(expected); +// } From d47a239d220f30fc163813a31a4120e7876b43be Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 12:11:17 +0100 Subject: [PATCH 07/13] add types for boot sector, partially support gridcase --- CMakeLists.txt | 2 +- ccos_boot_data.h | 308 ++++++++++++++++++++++++++++++++++++++++++++ ccos_format.c | 65 +++++----- ccos_format.h | 14 +- ccos_format_data.h | 173 ------------------------- ccos_structure.h | 36 ++++++ tests/format_test.c | 4 +- wrapper.c | 3 +- 8 files changed, 393 insertions(+), 212 deletions(-) create mode 100644 ccos_boot_data.h delete mode 100644 ccos_format_data.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b4bf332..71e5cec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(ccos_api STATIC ${SOURCE_DIR}/common.c ${SOURCE_DIR}/ccos_image.h ${SOURCE_DIR}/ccos_image.c - ${SOURCE_DIR}/ccos_format_data.h + ${SOURCE_DIR}/ccos_boot_data.h ${SOURCE_DIR}/ccos_format.h ${SOURCE_DIR}/ccos_format.c ${SOURCE_DIR}/ccos_private.h diff --git a/ccos_boot_data.h b/ccos_boot_data.h new file mode 100644 index 0000000..33f2791 --- /dev/null +++ b/ccos_boot_data.h @@ -0,0 +1,308 @@ +#ifndef CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H +#define CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H + +#include +#include + +#define BOOT_SECTOR_HEADER_SIZE 14 +#define BOOT_SECTOR_CODE_SIZE 406 +#define BOOT_CODE_SIZE 2048 + +const uint8_t COMPASS_BOOT_SECTOR_HEADER[BOOT_SECTOR_HEADER_SIZE] = "System Disk!!"; + +const uint8_t COMPASS_BOOT_CODE[BOOT_CODE_SIZE] = { + 0x9A, 0x42, 0x07, 0x01, 0x20, 0x55, 0xB8, 0x80, 0x20, 0x8E, 0xD8, 0xBB, 0x08, 0x00, 0x58, 0x59, + 0x89, 0x0F, 0x89, 0x47, 0x02, 0xEB, 0xE9, 0x55, 0x43, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, + 0x6F, 0x6F, 0x74, 0x3A, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, + 0x72, 0x0D, 0x0A, 0x43, 0x43, 0x4F, 0x53, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x66, 0x6F, 0x75, 0x6E, + 0x64, 0x0D, 0x0A, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, + 0x72, 0x20, 0x69, 0x6E, 0x20, 0x43, 0x43, 0x4F, 0x53, 0x0D, 0x0A, 0x11, 0x50, 0x72, 0x6F, 0x67, + 0x72, 0x61, 0x6D, 0x73, 0x7E, 0x53, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x7E, 0x0C, 0x43, 0x43, + 0x4F, 0x53, 0x7E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x7E, 0x18, 0x53, 0x63, 0x72, 0x65, 0x65, + 0x6E, 0x2E, 0x49, 0x6E, 0x69, 0x74, 0x7E, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x49, 0x6D, 0x61, + 0x67, 0x65, 0x7E, 0x55, 0x80, 0x20, 0x00, 0x00, 0x40, 0x00, 0x55, 0x8B, 0xEC, 0xB8, 0x08, 0x00, + 0x0E, 0x50, 0xB8, 0x0D, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0x8B, 0x1E, 0x00, 0x00, 0x4B, + 0xD1, 0xE3, 0x2E, 0xFF, 0xA7, 0xA7, 0x00, 0xAD, 0x00, 0xB7, 0x00, 0xC1, 0x00, 0xB8, 0x15, 0x00, + 0x0E, 0x50, 0xB8, 0x0E, 0x00, 0xEB, 0x12, 0xB8, 0x23, 0x00, 0x0E, 0x50, 0xB8, 0x10, 0x00, 0xEB, + 0x08, 0xB8, 0x33, 0x00, 0x0E, 0x50, 0xB8, 0x18, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0xB8, + 0xE8, 0x03, 0x50, 0x9A, 0xD3, 0x00, 0xEF, 0xFF, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB0, 0x00, 0xBF, + 0x99, 0x0E, 0xB9, 0x13, 0x00, 0x1E, 0x07, 0xFC, 0xF2, 0xAA, 0xA0, 0xB0, 0x0E, 0xA2, 0xA7, 0x0E, + 0xC4, 0x46, 0x0A, 0xA3, 0x9B, 0x0E, 0x8C, 0x06, 0x9D, 0x0E, 0x8B, 0x46, 0x04, 0xA3, 0xA3, 0x0E, + 0x8B, 0x46, 0x06, 0x8B, 0x56, 0x08, 0xA3, 0x9F, 0x0E, 0x89, 0x16, 0xA1, 0x0E, 0x5D, 0xC2, 0x0A, + 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x04, 0x06, 0x50, 0x8B, 0x46, 0x08, 0xBA, 0x00, 0x00, 0x03, + 0x06, 0x0C, 0x00, 0x13, 0x16, 0x0E, 0x00, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0xAA, 0xFF, + 0xB8, 0x04, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x6C, 0x0A, 0x1E, 0x50, 0xFF, 0x1E, + 0xAC, 0x0E, 0xA1, 0x6C, 0x0A, 0x5D, 0xC2, 0x06, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, 0x04, 0x8D, + 0x47, 0x04, 0xA3, 0x72, 0x0A, 0x8C, 0x06, 0x74, 0x0A, 0xC4, 0x5E, 0x04, 0xB8, 0x00, 0x00, 0x26, + 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x87, 0x06, 0x04, 0x26, 0xC7, 0x07, 0x01, 0x00, 0x26, 0xC7, + 0x47, 0x02, 0x00, 0x00, 0xC4, 0x1E, 0x72, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, 0x6E, 0x0A, 0x8C, + 0x06, 0x70, 0x0A, 0x89, 0xC3, 0x8B, 0x4E, 0x08, 0x26, 0x89, 0x4F, 0x06, 0x5D, 0xC2, 0x06, 0x00, + 0x55, 0x8B, 0xEC, 0x83, 0x7E, 0x04, 0x00, 0x75, 0x08, 0xA1, 0x24, 0x00, 0x2D, 0xD4, 0x00, 0xEB, + 0x06, 0xA1, 0x24, 0x00, 0x83, 0xE8, 0x0C, 0xD1, 0xE8, 0x5D, 0xC2, 0x02, 0x00, 0x55, 0x8B, 0xEC, + 0xB8, 0x00, 0x00, 0x50, 0xE8, 0xD9, 0xFF, 0xA3, 0x76, 0x0A, 0xC4, 0x5E, 0x04, 0x8D, 0x4F, 0x04, + 0x89, 0x0E, 0x86, 0x0A, 0x8C, 0x06, 0x88, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x8B, 0x87, 0x04, 0x04, + 0x26, 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x24, 0x00, 0xBF, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x7B, + 0x20, 0xA3, 0x7A, 0x0A, 0x3B, 0x06, 0x76, 0x0A, 0x73, 0x0D, 0xA3, 0x7C, 0x0A, 0xC4, 0x1E, 0x86, + 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xEB, 0x1E, 0xA1, 0x7A, 0x0A, 0x2B, 0x06, 0x76, 0x0A, 0x50, 0xB9, + 0x01, 0x00, 0x51, 0xE8, 0x8A, 0xFF, 0x89, 0xC1, 0x58, 0x31, 0xD2, 0xF7, 0xF1, 0x89, 0x16, 0x7C, + 0x0A, 0xC4, 0x06, 0x86, 0x0A, 0xA3, 0x7E, 0x0A, 0x8C, 0x06, 0x80, 0x0A, 0x83, 0x3E, 0x7C, 0x0A, + 0x00, 0x75, 0x5A, 0xC4, 0x06, 0x7E, 0x0A, 0xA3, 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xA1, 0x76, + 0x0A, 0x3B, 0x06, 0x7A, 0x0A, 0x75, 0x0F, 0xC4, 0x1E, 0x86, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, + 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xC4, 0x1E, 0x82, 0x0A, 0x26, 0xFF, 0x77, 0x06, 0xC4, 0x5E, + 0x04, 0x8D, 0x47, 0x04, 0x06, 0x50, 0xE8, 0xB8, 0xFE, 0xA3, 0x78, 0x0A, 0x09, 0xC0, 0x75, 0x37, + 0x83, 0x3E, 0x7A, 0x0A, 0x00, 0x75, 0x16, 0xC4, 0x1E, 0x86, 0x0A, 0x26, 0x8B, 0x47, 0x04, 0x26, + 0x8B, 0x57, 0x06, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0x26, 0x89, 0x57, 0x02, 0x8B, 0x36, 0x7C, + 0x0A, 0xD1, 0xE6, 0xC4, 0x1E, 0x7E, 0x0A, 0x26, 0xFF, 0x70, 0x0C, 0xC4, 0x5E, 0x04, 0x8D, 0x87, + 0x04, 0x02, 0x06, 0x50, 0xE8, 0x7A, 0xFE, 0x5D, 0xC2, 0x04, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, + 0x0A, 0x8D, 0x87, 0x04, 0x02, 0xA3, 0x92, 0x0A, 0x8C, 0x06, 0x94, 0x0A, 0xC7, 0x06, 0x8E, 0x0A, + 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0x97, 0x06, 0x04, 0x26, + 0x3B, 0x57, 0x02, 0x75, 0x03, 0x26, 0x3B, 0x07, 0xB0, 0xFF, 0x74, 0x01, 0x40, 0xA2, 0xB1, 0x0E, + 0xA1, 0x8E, 0x0A, 0x3B, 0x46, 0x04, 0x72, 0x03, 0xE9, 0xE5, 0x00, 0xA0, 0xB1, 0x0E, 0xD0, 0xD8, + 0x73, 0x03, 0xE9, 0xDB, 0x00, 0x8B, 0x0E, 0x24, 0x00, 0xBA, 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, + 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0xBF, 0x06, 0x04, 0x87, 0xFA, 0x51, 0x57, 0x9A, 0x00, 0x00, + 0x7B, 0x20, 0x89, 0x3E, 0x8A, 0x0A, 0x5B, 0x58, 0x2B, 0xC7, 0xA3, 0x8C, 0x0A, 0x09, 0xFF, 0x75, + 0x0F, 0xC4, 0x46, 0x0A, 0x06, 0x50, 0xE8, 0x94, 0xFE, 0x09, 0xC0, 0x74, 0x03, 0xE9, 0xA0, 0x00, + 0x8B, 0x0E, 0x8C, 0x0A, 0xA1, 0x8E, 0x0A, 0x03, 0xC8, 0x8B, 0x46, 0x04, 0x3B, 0xC8, 0x76, 0x07, + 0x2B, 0x06, 0x8E, 0x0A, 0xA3, 0x8C, 0x0A, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, + 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x8C, 0x0A, 0xBF, 0x00, 0x00, 0x03, 0xC8, 0x13, 0xFA, 0x26, + 0x8B, 0x37, 0x26, 0x8B, 0x47, 0x02, 0x3B, 0xF8, 0x75, 0x02, 0x3B, 0xCE, 0x76, 0x15, 0x26, 0x2B, + 0xB7, 0x04, 0x04, 0x26, 0x1B, 0x87, 0x06, 0x04, 0x89, 0x36, 0x90, 0x0A, 0xC6, 0x06, 0xB1, 0x0E, + 0x01, 0xEB, 0x06, 0xA1, 0x8C, 0x0A, 0xA3, 0x90, 0x0A, 0xC4, 0x1E, 0x92, 0x0A, 0x8B, 0x36, 0x8A, + 0x0A, 0x8D, 0x70, 0x04, 0x06, 0xC4, 0x5E, 0x06, 0x8B, 0x3E, 0x8E, 0x0A, 0x8D, 0x39, 0x8B, 0x0E, + 0x90, 0x0A, 0x1E, 0x8E, 0x9E, 0xFE, 0xFF, 0xFC, 0xF2, 0xA4, 0x1F, 0x59, 0xA1, 0x90, 0x0A, 0x01, + 0x06, 0x8E, 0x0A, 0xC4, 0x5E, 0x0A, 0xBA, 0x00, 0x00, 0x26, 0x03, 0x87, 0x04, 0x04, 0x26, 0x13, + 0x97, 0x06, 0x04, 0x26, 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x97, 0x06, 0x04, 0xE9, 0x10, 0xFF, + 0xA1, 0x8E, 0x0A, 0x5D, 0xC2, 0x0A, 0x00, 0x55, 0x8B, 0xEC, 0xA1, 0x00, 0x00, 0x09, 0xC0, 0x75, + 0x2D, 0xFF, 0x76, 0x0C, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xE8, 0x6D, 0xFD, 0xB8, 0x58, 0x00, 0x1E, + 0x50, 0xB8, 0xEF, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0xAE, 0xFE, 0xA3, 0x98, 0x0A, + 0x09, 0xC0, 0x74, 0x07, 0x80, 0x3E, 0xEF, 0x0E, 0xFF, 0x75, 0x05, 0xB8, 0x02, 0x00, 0xEB, 0x6B, + 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0x96, 0x0A, 0x1E, 0x50, 0xB8, 0x02, 0x00, 0x50, 0xE8, 0x8A, + 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB2, 0x0E, 0x1E, 0x50, 0xB8, 0x01, + 0x00, 0x50, 0xE8, 0x76, 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB3, 0x0E, + 0x1E, 0x50, 0xA0, 0xB2, 0x0E, 0xB4, 0x00, 0x50, 0xE8, 0x60, 0xFE, 0xA3, 0x98, 0x0A, 0xC4, 0x5E, + 0x08, 0xA0, 0xB2, 0x0E, 0x26, 0x38, 0x07, 0x75, 0x26, 0xB9, 0xB3, 0x0E, 0x1E, 0x51, 0x8D, 0x4F, + 0x01, 0x06, 0x51, 0xB4, 0x00, 0x50, 0x9A, 0xEC, 0x00, 0xEF, 0xFF, 0xD0, 0xD8, 0x73, 0x10, 0xA1, + 0x96, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0xB8, 0x00, 0x00, 0x5D, 0xC2, 0x0A, 0x00, 0xB8, + 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xF0, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0x1B, 0xFE, + 0xA3, 0x98, 0x0A, 0xE9, 0x56, 0xFF, 0x55, 0x8B, 0xEC, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xB8, 0x18, + 0x00, 0x1E, 0x50, 0xB8, 0x0A, 0x00, 0x50, 0xE8, 0x01, 0xFE, 0xA3, 0x9C, 0x0A, 0xC7, 0x06, 0x9E, + 0x0A, 0x00, 0x00, 0xC7, 0x06, 0x9C, 0x0A, 0xEC, 0x03, 0xB8, 0xEC, 0x03, 0x39, 0x06, 0x9C, 0x0A, + 0x75, 0x1E, 0xB9, 0x60, 0x04, 0x1E, 0x51, 0xC4, 0x1E, 0x1A, 0x00, 0x8B, 0x36, 0x9E, 0x0A, 0x8D, + 0x08, 0x06, 0x51, 0x50, 0xE8, 0xD4, 0xFD, 0xA3, 0x9C, 0x0A, 0x01, 0x06, 0x9E, 0x0A, 0xEB, 0xD9, + 0xB8, 0x1A, 0x00, 0x1E, 0x50, 0xB8, 0x08, 0x00, 0x50, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x50, 0xC4, + 0x06, 0x1A, 0x00, 0x06, 0x50, 0xFF, 0x36, 0x9E, 0x0A, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x59, 0x03, + 0xC1, 0x3B, 0x06, 0x18, 0x00, 0x74, 0x06, 0xC7, 0x06, 0x00, 0x00, 0x03, 0x00, 0x5D, 0xC3, 0x55, + 0x8B, 0xEC, 0xB0, 0x00, 0xA2, 0x2F, 0x00, 0xA2, 0x56, 0x00, 0xA1, 0x76, 0x08, 0x09, 0xC0, 0x74, + 0x24, 0xA3, 0x50, 0x00, 0xA1, 0x78, 0x08, 0xA3, 0x52, 0x00, 0x8B, 0x0E, 0x7A, 0x08, 0x89, 0x0E, + 0x54, 0x00, 0x8A, 0x16, 0x7E, 0x08, 0x88, 0x16, 0x57, 0x00, 0xF7, 0xE1, 0xF7, 0x26, 0x7C, 0x08, + 0xA3, 0x26, 0x00, 0xEB, 0x17, 0xC7, 0x06, 0x52, 0x00, 0x09, 0x00, 0xC7, 0x06, 0x54, 0x00, 0x02, + 0x00, 0xC6, 0x06, 0x57, 0x00, 0x01, 0xC7, 0x06, 0x26, 0x00, 0xD0, 0x02, 0xB8, 0x22, 0x00, 0x1E, + 0x50, 0xB8, 0xFF, 0xFF, 0x89, 0xC2, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0x7B, 0xFB, 0xC6, + 0x06, 0xA5, 0x0E, 0x01, 0xB8, 0x05, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0xA0, 0x0A, + 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB8, 0x00, 0x00, 0x89, 0xC2, + 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xC6, 0x06, 0xF1, 0x0E, 0x01, 0xC6, 0x06, 0xB0, 0x0E, + 0x04, 0xBF, 0xEF, 0xFF, 0xB9, 0x24, 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0x80, + 0x3E, 0xB0, 0x0A, 0x62, 0x75, 0x18, 0xC6, 0x06, 0xB0, 0x0E, 0xFF, 0xBF, 0xEF, 0xFF, 0xB9, 0x1A, + 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0xA2, 0xF1, 0x0E, 0xEB, 0x1A, 0x80, 0x3E, + 0xB0, 0x0A, 0x63, 0x75, 0x07, 0xC6, 0x06, 0xB0, 0x0E, 0x06, 0xEB, 0x0C, 0x80, 0x3E, 0xB0, 0x0A, + 0x77, 0x74, 0x05, 0xC6, 0x06, 0xB0, 0x0E, 0x05, 0xB8, 0x22, 0x00, 0x1E, 0x50, 0xB8, 0x00, 0x00, + 0x89, 0xC2, 0x52, 0x50, 0xB8, 0x36, 0x00, 0x50, 0xE8, 0xEF, 0xFA, 0xB8, 0x01, 0x00, 0x50, 0xB8, + 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x00, 0x00, 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x83, 0x3E, 0x00, + 0x00, 0x00, 0x74, 0x02, 0x5D, 0xC3, 0xB8, 0x00, 0x02, 0x31, 0xD2, 0xF7, 0x36, 0x22, 0x00, 0xA3, + 0xA2, 0x0A, 0xB8, 0x68, 0x08, 0xA3, 0xA4, 0x0A, 0x8C, 0x1E, 0xA6, 0x0A, 0xC6, 0x06, 0xF2, 0x0E, + 0x00, 0xA1, 0xA2, 0x0A, 0x48, 0x8A, 0x0E, 0xF2, 0x0E, 0xB5, 0x00, 0x3B, 0xC8, 0x77, 0x29, 0x83, + 0x3E, 0x00, 0x00, 0x00, 0x75, 0x1C, 0xB8, 0x00, 0x00, 0x50, 0x8B, 0x16, 0x22, 0x00, 0x89, 0xD0, + 0xF7, 0xE1, 0x89, 0xC6, 0xC4, 0x1E, 0xA4, 0x0A, 0x8D, 0x00, 0x06, 0x50, 0xE8, 0xC2, 0xFA, 0xA3, + 0x00, 0x00, 0xFE, 0x06, 0xF2, 0x0E, 0x75, 0xC9, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x74, 0x02, 0x5D, + 0xC3, 0xA0, 0xF1, 0x0E, 0xD0, 0xD8, 0x73, 0x0B, 0x81, 0x3E, 0x26, 0x00, 0x40, 0x1F, 0x73, 0x03, + 0xE8, 0x8C, 0xFE, 0x81, 0x3E, 0x24, 0x0A, 0xAA, 0x55, 0x75, 0x1D, 0xA1, 0x08, 0x00, 0x8B, 0x16, + 0x0A, 0x00, 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xB8, 0x00, 0x00, 0x50, 0xB8, 0x68, 0x08, + 0x1E, 0x50, 0xE8, 0x7C, 0xFA, 0xA3, 0x00, 0x00, 0xA1, 0x88, 0x08, 0x09, 0xC0, 0x74, 0x03, 0xA3, + 0x2B, 0x00, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0x9A, 0x15, 0x00, 0xEF, 0xFF, 0x89, 0x1E, 0x14, 0x00, + 0x8C, 0x06, 0x16, 0x00, 0x26, 0x8A, 0x47, 0x16, 0xA2, 0xB0, 0x0A, 0xE8, 0xBA, 0xFE, 0xFF, 0x36, + 0x2B, 0x00, 0xB8, 0x4B, 0x00, 0x0E, 0x50, 0xB8, 0xAA, 0x0A, 0x1E, 0x50, 0xE8, 0xF8, 0xFC, 0xA3, + 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x5D, 0x00, 0x0E, 0x50, 0xB8, 0xAC, 0x0A, 0x1E, 0x50, + 0xE8, 0xE4, 0xFC, 0xA3, 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x6A, 0x00, 0x0E, 0x50, 0xB8, + 0xAE, 0x0A, 0x1E, 0x50, 0xE8, 0xD0, 0xFC, 0x09, 0xC0, 0x75, 0x22, 0xFF, 0x36, 0xAE, 0x0A, 0xB8, + 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x42, 0xFA, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0x2E, 0xC4, 0x06, 0x86, + 0x00, 0x06, 0x50, 0xB8, 0x80, 0x25, 0x50, 0xE8, 0x81, 0xFB, 0xA3, 0xA8, 0x0A, 0x83, 0x3E, 0x00, + 0x00, 0x00, 0x75, 0x18, 0xFF, 0x36, 0xAC, 0x0A, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x19, 0xFA, + 0xE8, 0x53, 0xFD, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x75, 0x02, 0x5D, 0xC3, 0xE8, 0x4B, 0xF9, 0xE9, + 0x79, 0xFF, 0x1E, 0x2E, 0x8E, 0x1E, 0x84, 0x00, 0x55, 0x8B, 0xEC, 0x89, 0xE0, 0xA3, 0x02, 0x00, + 0x8C, 0xD0, 0xA3, 0x04, 0x00, 0xB8, 0xB1, 0x0A, 0xA3, 0x10, 0x00, 0x8C, 0x1E, 0x12, 0x00, 0xFA, + 0xA1, 0x10, 0x00, 0x8B, 0x16, 0x12, 0x00, 0x05, 0xE8, 0x03, 0x83, 0xE8, 0x0A, 0x89, 0xC4, 0xA1, + 0x12, 0x00, 0x8E, 0xD0, 0xFB, 0xE8, 0x2C, 0xFF, 0xFA, 0xA1, 0x02, 0x00, 0x89, 0xC4, 0xA1, 0x04, + 0x00, 0x8E, 0xD0, 0xFB, 0xFF, 0x36, 0x0E, 0x00, 0xFF, 0x36, 0x0C, 0x00, 0xB8, 0x01, 0x00, 0x50, + 0xB8, 0x21, 0x43, 0x50, 0xFF, 0x1E, 0x1E, 0x00, 0x5D, 0x1F, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x0B, 0xFF, 0x75, 0x1D, 0x3B, 0xCA, 0x76, 0x09, 0xF7, 0xF1, 0x33, 0xF6, 0x8B, 0xFA, 0x33, 0xD2, + 0xCB, 0x8B, 0xF8, 0x8B, 0xC2, 0x33, 0xD2, 0xF7, 0xF1, 0x97, 0xF7, 0xF1, 0x87, 0xD7, 0x33, 0xF6, + 0xCB, 0x55, 0x8B, 0xE9, 0x8B, 0xDF, 0x33, 0xF6, 0x8B, 0xFE, 0xB9, 0x20, 0x00, 0xD1, 0xE7, 0xD1, + 0xD6, 0xD1, 0xE0, 0xD1, 0xD2, 0x83, 0xD7, 0x00, 0x2B, 0xFD, 0x1B, 0xF3, 0x40, 0x73, 0x05, 0x03, + 0xFD, 0x13, 0xF3, 0x48, 0xE2, 0xE7, 0x5D, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x76, 0x65, +}; + +const uint8_t GRIDCASE_BOOT_SECTOR_HEADER[BOOT_SECTOR_HEADER_SIZE] = { + 0xBB, 0xBE, 0x01, 0x90, 0x81, 0xC3, 0x00, 0x7C, 0x2E, 0x88, 0x57, 0x0E, 0xEB, 0x18, +}; + +const uint8_t GRIDCASE_BOOT_SECTOR_CODE[BOOT_SECTOR_CODE_SIZE] = { + 0x80, 0x3C, 0x80, 0x75, 0x06, 0x8B, 0x54, 0x08, 0xEB, 0x03, 0x90, 0x33, 0xD2, 0x8C, 0xC8, 0x8E, + 0xD8, 0xB8, 0xC0, 0x1D, 0x8E, 0xC0, 0x33, 0xFF, 0xBE, 0x00, 0x7C, 0xB9, 0x00, 0x02, 0xFC, 0xF3, + 0xA4, 0xFA, 0xB8, 0xC0, 0x1C, 0x8E, 0xD0, 0xBC, 0x00, 0x10, 0xFB, 0xB8, 0xC0, 0x1D, 0x50, 0xB8, + 0x56, 0x01, 0x50, 0xCB, 0x8C, 0xCB, 0x8E, 0xDB, 0x80, 0xFA, 0x80, 0x74, 0x07, 0xBE, 0xD1, 0x01, + 0x90, 0xEB, 0x05, 0x90, 0xBE, 0xE7, 0x01, 0x90, 0xC3, 0x1E, 0x55, 0x8B, 0xEC, 0x8B, 0x46, 0x10, + 0x3D, 0x00, 0x00, 0x74, 0x17, 0x3D, 0x01, 0x00, 0x74, 0x1F, 0x3D, 0x04, 0x00, 0x74, 0x42, 0xB8, + 0x23, 0x00, 0xC5, 0x5E, 0x08, 0x89, 0x07, 0x5D, 0x1F, 0xCA, 0x0A, 0x00, 0xB4, 0x00, 0x55, 0xCD, + 0x13, 0x5D, 0xB8, 0x00, 0x00, 0x72, 0x66, 0xEB, 0xE9, 0xFC, 0xC5, 0x5E, 0x0C, 0xC4, 0x7F, 0x02, + 0x57, 0x8A, 0x57, 0x0E, 0xE8, 0xAD, 0xFF, 0xB9, 0x15, 0x00, 0xF3, 0xA4, 0x5F, 0xBB, 0x0E, 0x00, + 0x8B, 0x47, 0x12, 0x3D, 0x00, 0x00, 0x74, 0x04, 0x26, 0x89, 0x45, 0x09, 0xB8, 0x00, 0x00, 0xEB, + 0xC1, 0xB9, 0x05, 0x00, 0x51, 0xC5, 0x76, 0x0C, 0x8B, 0x44, 0x06, 0x8A, 0x54, 0x0E, 0xE8, 0x31, + 0x00, 0xC4, 0x5C, 0x02, 0xB8, 0x01, 0x02, 0x55, 0xCD, 0x13, 0x5D, 0x59, 0x72, 0x05, 0xB8, 0x00, + 0x00, 0xEB, 0x9F, 0x80, 0xFC, 0x04, 0x75, 0x09, 0x2E, 0xC6, 0x06, 0xE5, 0x01, 0x00, 0x90, 0xE2, + 0xD3, 0x51, 0xB4, 0x00, 0x55, 0xCD, 0x13, 0x5D, 0x59, 0x72, 0x02, 0xE2, 0xC7, 0xB8, 0x6C, 0x00, + 0xEB, 0x80, 0x1E, 0x56, 0x52, 0xE8, 0x4C, 0xFF, 0x03, 0x06, 0xBC, 0x01, 0x50, 0x33, 0xD2, 0xF7, + 0x74, 0x10, 0x8B, 0xD8, 0x53, 0x33, 0xD2, 0xF7, 0x74, 0x12, 0x8B, 0xC8, 0xF7, 0x64, 0x12, 0x2B, + 0xD8, 0x58, 0xF7, 0x64, 0x10, 0x5A, 0x2B, 0xD0, 0x86, 0xCD, 0x8A, 0xC1, 0xB1, 0x06, 0xD2, 0xE0, + 0x8A, 0xC8, 0x02, 0xCA, 0xFE, 0xC1, 0x5A, 0x8A, 0xF3, 0xF6, 0xC2, 0x80, 0x75, 0x0F, 0x8A, 0x44, + 0x14, 0xA8, 0x01, 0x74, 0x08, 0xF6, 0xC6, 0xFF, 0x74, 0x03, 0x02, 0x4C, 0x10, 0x5E, 0x1F, 0xC3, + 0x8C, 0xC8, 0x8E, 0xD8, 0x89, 0x16, 0xBC, 0x01, 0xBB, 0xBE, 0x01, 0x90, 0xC7, 0x47, 0x02, 0x00, + 0x00, 0xC7, 0x47, 0x04, 0x00, 0x1E, 0xB9, 0x04, 0x00, 0x51, 0xB8, 0x04, 0x00, 0x50, 0x1E, 0x53, + 0x1E, 0xB8, 0xB6, 0x01, 0x50, 0xFF, 0x1E, 0xB8, 0x01, 0x90, 0x83, 0x3E, 0xB6, 0x01, 0x00, 0x74, + 0x0C, 0xB4, 0x0E, 0xB0, 0x45, 0xBB, 0x00, 0x00, 0xCD, 0x10, 0x5B, 0xFA, 0xF4, 0xBB, 0xBE, 0x01, + 0x90, 0x81, 0x47, 0x02, 0x00, 0x02, 0x80, 0x47, 0x06, 0x01, 0x59, 0xE2, 0xCC, 0x8B, 0x0E, 0xBC, + 0x01, 0x8A, 0x57, 0x0E, 0xBB, 0x6F, 0x00, 0xB8, 0x00, 0x1E, 0x50, 0xB8, 0x06, 0x00, 0x50, 0xCB, + 0x00, 0x00, 0x6F, 0x00, 0xC0, 0x1D, +}; + +const uint8_t GRIDCASE_BOOT_CODE[BOOT_CODE_SIZE] = { + 0x9A, 0xA1, 0x06, 0x02, 0x1E, 0x55, 0x1E, 0x53, 0xB8, 0x7B, 0x1E, 0x8E, 0xD8, 0x88, 0x16, 0xB9, + 0x0A, 0xBB, 0x0C, 0x00, 0x89, 0x0F, 0x33, 0xC0, 0x89, 0x47, 0x02, 0xB0, 0x02, 0xCD, 0x10, 0xEB, + 0xDF, 0x55, 0xCF, 0x02, 0x25, 0x02, 0x09, 0x2A, 0xFF, 0x50, 0xF6, 0x00, 0x04, 0x43, 0x61, 0x6E, + 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x3A, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, + 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x43, 0x43, 0x4F, 0x53, 0x20, 0x6E, 0x6F, 0x74, + 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x0D, 0x0A, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, + 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x43, 0x43, 0x4F, 0x53, 0x0D, 0x0A, + 0x11, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x73, 0x7E, 0x53, 0x75, 0x62, 0x6A, 0x65, 0x63, + 0x74, 0x7E, 0x0C, 0x43, 0x43, 0x4F, 0x53, 0x7E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x7E, 0x18, + 0x53, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x2E, 0x49, 0x6E, 0x69, 0x74, 0x7E, 0x53, 0x63, 0x72, 0x65, + 0x65, 0x6E, 0x49, 0x6D, 0x61, 0x67, 0x65, 0x7E, 0x53, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x67, + 0x20, 0x47, 0x52, 0x69, 0x44, 0x2D, 0x4F, 0x53, 0x0D, 0x0A, 0x7B, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xB8, 0x55, 0x8B, 0xEC, 0xE8, 0x89, 0x06, 0xB8, 0x0D, 0x00, 0x0E, 0x50, 0xB8, + 0x0D, 0x00, 0x50, 0xE8, 0x60, 0x06, 0x8B, 0x1E, 0x06, 0x00, 0x4B, 0xD1, 0xE3, 0x2E, 0xFF, 0xA7, + 0xC2, 0x00, 0xC8, 0x00, 0xD2, 0x00, 0xDC, 0x00, 0xB8, 0x1A, 0x00, 0x0E, 0x50, 0xB8, 0x0E, 0x00, + 0xEB, 0x12, 0xB8, 0x28, 0x00, 0x0E, 0x50, 0xB8, 0x10, 0x00, 0xEB, 0x08, 0xB8, 0x38, 0x00, 0x0E, + 0x50, 0xB8, 0x18, 0x00, 0x50, 0xE8, 0x2E, 0x06, 0xB8, 0x20, 0x4E, 0x0B, 0xC0, 0x74, 0x08, 0xB1, + 0x78, 0xD2, 0xE9, 0xFF, 0xC8, 0x75, 0xF8, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB0, 0x00, 0xBF, 0xA2, + 0x0E, 0xB9, 0x13, 0x00, 0x1E, 0x07, 0xFC, 0xF2, 0xAA, 0xA0, 0xB9, 0x0E, 0xA2, 0xB0, 0x0E, 0xC4, + 0x46, 0x0A, 0xA3, 0xA4, 0x0E, 0x8C, 0x06, 0xA6, 0x0E, 0x8B, 0x46, 0x04, 0xA3, 0xAC, 0x0E, 0x8B, + 0x46, 0x06, 0x8B, 0x56, 0x08, 0xA3, 0xA8, 0x0E, 0x89, 0x16, 0xAA, 0x0E, 0x5D, 0xC2, 0x0A, 0x00, + 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x04, 0x06, 0x50, 0x8B, 0x46, 0x08, 0xBA, 0x00, 0x00, 0x03, 0x06, + 0x10, 0x00, 0x13, 0x16, 0x12, 0x00, 0x52, 0x50, 0xFF, 0x36, 0x2A, 0x00, 0xE8, 0xAA, 0xFF, 0xB8, + 0x04, 0x00, 0x50, 0xB8, 0xA2, 0x0E, 0x1E, 0x50, 0xB8, 0x78, 0x0A, 0x1E, 0x50, 0xFF, 0x1E, 0xB5, + 0x0E, 0xA1, 0x78, 0x0A, 0x5D, 0xC2, 0x06, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, 0x04, 0x8D, 0x47, + 0x04, 0xA3, 0x7E, 0x0A, 0x8C, 0x06, 0x80, 0x0A, 0xC4, 0x5E, 0x04, 0xB8, 0x00, 0x00, 0x26, 0x89, + 0x87, 0x04, 0x04, 0x26, 0x89, 0x87, 0x06, 0x04, 0x26, 0xC7, 0x07, 0x01, 0x00, 0x26, 0xC7, 0x47, + 0x02, 0x00, 0x00, 0xC4, 0x1E, 0x7E, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, 0x7A, 0x0A, 0x8C, 0x06, + 0x7C, 0x0A, 0x89, 0xC3, 0x8B, 0x4E, 0x08, 0x26, 0x89, 0x4F, 0x06, 0x5D, 0xC2, 0x06, 0x00, 0x55, + 0x8B, 0xEC, 0x83, 0x7E, 0x04, 0x00, 0x75, 0x08, 0xA1, 0x2C, 0x00, 0x2D, 0xD4, 0x00, 0xEB, 0x06, + 0xA1, 0x2C, 0x00, 0x83, 0xE8, 0x0C, 0xD1, 0xE8, 0x5D, 0xC2, 0x02, 0x00, 0x55, 0x8B, 0xEC, 0xB8, + 0x00, 0x00, 0x50, 0xE8, 0xD9, 0xFF, 0xA3, 0x82, 0x0A, 0xC4, 0x5E, 0x04, 0x8D, 0x4F, 0x04, 0x89, + 0x0E, 0x92, 0x0A, 0x8C, 0x06, 0x94, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, + 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x2C, 0x00, 0xBF, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x76, 0x1E, + 0xA3, 0x86, 0x0A, 0x3B, 0x06, 0x82, 0x0A, 0x73, 0x0D, 0xA3, 0x88, 0x0A, 0xC4, 0x1E, 0x92, 0x0A, + 0x8D, 0x87, 0xCC, 0x00, 0xEB, 0x1E, 0xA1, 0x86, 0x0A, 0x2B, 0x06, 0x82, 0x0A, 0x50, 0xB9, 0x01, + 0x00, 0x51, 0xE8, 0x8A, 0xFF, 0x89, 0xC1, 0x58, 0x31, 0xD2, 0xF7, 0xF1, 0x89, 0x16, 0x88, 0x0A, + 0xC4, 0x06, 0x92, 0x0A, 0xA3, 0x8A, 0x0A, 0x8C, 0x06, 0x8C, 0x0A, 0x83, 0x3E, 0x88, 0x0A, 0x00, + 0x75, 0x5A, 0xC4, 0x06, 0x8A, 0x0A, 0xA3, 0x8E, 0x0A, 0x8C, 0x06, 0x90, 0x0A, 0xA1, 0x82, 0x0A, + 0x3B, 0x06, 0x86, 0x0A, 0x75, 0x0F, 0xC4, 0x1E, 0x92, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, 0x8E, + 0x0A, 0x8C, 0x06, 0x90, 0x0A, 0xC4, 0x1E, 0x8E, 0x0A, 0x26, 0xFF, 0x77, 0x06, 0xC4, 0x5E, 0x04, + 0x8D, 0x47, 0x04, 0x06, 0x50, 0xE8, 0xB8, 0xFE, 0xA3, 0x84, 0x0A, 0x09, 0xC0, 0x75, 0x37, 0x83, + 0x3E, 0x86, 0x0A, 0x00, 0x75, 0x16, 0xC4, 0x1E, 0x92, 0x0A, 0x26, 0x8B, 0x47, 0x04, 0x26, 0x8B, + 0x57, 0x06, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0x26, 0x89, 0x57, 0x02, 0x8B, 0x36, 0x88, 0x0A, + 0xD1, 0xE6, 0xC4, 0x1E, 0x8A, 0x0A, 0x26, 0xFF, 0x70, 0x0C, 0xC4, 0x5E, 0x04, 0x8D, 0x87, 0x04, + 0x02, 0x06, 0x50, 0xE8, 0x7A, 0xFE, 0x5D, 0xC2, 0x04, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, 0x0A, + 0x8D, 0x87, 0x04, 0x02, 0xA3, 0x9E, 0x0A, 0x8C, 0x06, 0xA0, 0x0A, 0xC7, 0x06, 0x9A, 0x0A, 0x00, + 0x00, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0x97, 0x06, 0x04, 0x26, 0x3B, + 0x57, 0x02, 0x75, 0x03, 0x26, 0x3B, 0x07, 0xB0, 0xFF, 0x74, 0x01, 0x40, 0xA2, 0xBA, 0x0E, 0xA1, + 0x9A, 0x0A, 0x3B, 0x46, 0x04, 0x72, 0x03, 0xE9, 0xE5, 0x00, 0xA0, 0xBA, 0x0E, 0xD0, 0xD8, 0x73, + 0x03, 0xE9, 0xDB, 0x00, 0x8B, 0x0E, 0x2C, 0x00, 0xBA, 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, + 0x87, 0x04, 0x04, 0x26, 0x8B, 0xBF, 0x06, 0x04, 0x87, 0xFA, 0x51, 0x57, 0x9A, 0x00, 0x00, 0x76, + 0x1E, 0x89, 0x3E, 0x96, 0x0A, 0x5B, 0x58, 0x2B, 0xC7, 0xA3, 0x98, 0x0A, 0x09, 0xFF, 0x75, 0x0F, + 0xC4, 0x46, 0x0A, 0x06, 0x50, 0xE8, 0x94, 0xFE, 0x09, 0xC0, 0x74, 0x03, 0xE9, 0xA0, 0x00, 0x8B, + 0x0E, 0x98, 0x0A, 0xA1, 0x9A, 0x0A, 0x03, 0xC8, 0x8B, 0x46, 0x04, 0x3B, 0xC8, 0x76, 0x07, 0x2B, + 0x06, 0x9A, 0x0A, 0xA3, 0x98, 0x0A, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, + 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x98, 0x0A, 0xBF, 0x00, 0x00, 0x03, 0xC8, 0x13, 0xFA, 0x26, 0x8B, + 0x37, 0x26, 0x8B, 0x47, 0x02, 0x3B, 0xF8, 0x75, 0x02, 0x3B, 0xCE, 0x76, 0x15, 0x26, 0x2B, 0xB7, + 0x04, 0x04, 0x26, 0x1B, 0x87, 0x06, 0x04, 0x89, 0x36, 0x9C, 0x0A, 0xC6, 0x06, 0xBA, 0x0E, 0x01, + 0xEB, 0x06, 0xA1, 0x98, 0x0A, 0xA3, 0x9C, 0x0A, 0xC4, 0x1E, 0x9E, 0x0A, 0x8B, 0x36, 0x96, 0x0A, + 0x8D, 0x70, 0x04, 0x06, 0xC4, 0x5E, 0x06, 0x8B, 0x3E, 0x9A, 0x0A, 0x8D, 0x39, 0x8B, 0x0E, 0x9C, + 0x0A, 0x1E, 0x8E, 0x9E, 0xFE, 0xFF, 0xFC, 0xF2, 0xA4, 0x1F, 0x59, 0xA1, 0x9C, 0x0A, 0x01, 0x06, + 0x9A, 0x0A, 0xC4, 0x5E, 0x0A, 0xBA, 0x00, 0x00, 0x26, 0x03, 0x87, 0x04, 0x04, 0x26, 0x13, 0x97, + 0x06, 0x04, 0x26, 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x97, 0x06, 0x04, 0xE9, 0x10, 0xFF, 0xA1, + 0x9A, 0x0A, 0x5D, 0xC2, 0x0A, 0x00, 0x55, 0x8B, 0xEC, 0xA1, 0x06, 0x00, 0x09, 0xC0, 0x75, 0x2D, + 0xFF, 0x76, 0x0C, 0xB8, 0x60, 0x00, 0x1E, 0x50, 0xE8, 0x6D, 0xFD, 0xB8, 0x60, 0x00, 0x1E, 0x50, + 0xB8, 0xF8, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0xAE, 0xFE, 0xA3, 0xA4, 0x0A, 0x09, + 0xC0, 0x74, 0x07, 0x80, 0x3E, 0xF8, 0x0E, 0xFF, 0x75, 0x05, 0xB8, 0x02, 0x00, 0xEB, 0x6B, 0xB8, + 0x60, 0x00, 0x1E, 0x50, 0xB8, 0xA2, 0x0A, 0x1E, 0x50, 0xB8, 0x02, 0x00, 0x50, 0xE8, 0x8A, 0xFE, + 0xA3, 0xA4, 0x0A, 0xB8, 0x60, 0x00, 0x1E, 0x50, 0xB8, 0xBB, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, + 0x50, 0xE8, 0x76, 0xFE, 0xA3, 0xA4, 0x0A, 0xB8, 0x60, 0x00, 0x1E, 0x50, 0xB8, 0xBC, 0x0E, 0x1E, + 0x50, 0xA0, 0xBB, 0x0E, 0xB4, 0x00, 0x50, 0xE8, 0x60, 0xFE, 0xA3, 0xA4, 0x0A, 0xC4, 0x5E, 0x08, + 0xA0, 0xBB, 0x0E, 0x26, 0x38, 0x07, 0x75, 0x26, 0xB9, 0xBC, 0x0E, 0x1E, 0x51, 0x8D, 0x4F, 0x01, + 0x06, 0x51, 0xB4, 0x00, 0x50, 0x9A, 0x0D, 0x01, 0xEA, 0xFD, 0xD0, 0xD8, 0x73, 0x10, 0xA1, 0xA2, + 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0xB8, 0x00, 0x00, 0x5D, 0xC2, 0x0A, 0x00, 0xB8, 0x60, + 0x00, 0x1E, 0x50, 0xB8, 0xF9, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0x1B, 0xFE, 0xA3, + 0xA4, 0x0A, 0xE9, 0x56, 0xFF, 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x04, 0x06, 0x50, 0xB8, 0x20, 0x00, + 0x1E, 0x50, 0xB8, 0x0A, 0x00, 0x50, 0xE8, 0x01, 0xFE, 0xA3, 0xAA, 0x0A, 0xB8, 0x22, 0x00, 0x1E, + 0x50, 0xB8, 0x08, 0x00, 0x50, 0x9A, 0x12, 0x01, 0xEA, 0xFD, 0xA3, 0xA8, 0x0A, 0xC7, 0x06, 0xAA, + 0x0A, 0x00, 0x04, 0xC4, 0x06, 0x22, 0x00, 0xA3, 0xAC, 0x0A, 0x8C, 0x06, 0xAE, 0x0A, 0xB8, 0x00, + 0x04, 0x39, 0x06, 0xAA, 0x0A, 0x75, 0x35, 0xC4, 0x46, 0x04, 0x06, 0x50, 0xC4, 0x06, 0xAC, 0x0A, + 0x06, 0x50, 0xB8, 0x00, 0x04, 0x50, 0xE8, 0xC1, 0xFD, 0xA3, 0xAA, 0x0A, 0xC4, 0x06, 0xAC, 0x0A, + 0x06, 0x50, 0xFF, 0x36, 0xAA, 0x0A, 0x9A, 0x12, 0x01, 0xEA, 0xFD, 0x01, 0x06, 0xA8, 0x0A, 0xA1, + 0xAA, 0x0A, 0xB1, 0x04, 0xD3, 0xE8, 0x01, 0x06, 0xAE, 0x0A, 0xEB, 0xC2, 0xA1, 0x20, 0x00, 0x3B, + 0x06, 0xA8, 0x0A, 0x74, 0x06, 0xC7, 0x06, 0x06, 0x00, 0x03, 0x00, 0x5D, 0xC2, 0x04, 0x00, 0x55, + 0x8B, 0xEC, 0xB8, 0x00, 0x00, 0x89, 0xC2, 0xA3, 0x10, 0x00, 0x89, 0x16, 0x12, 0x00, 0xC4, 0x06, + 0x18, 0x00, 0xA3, 0xB5, 0x0E, 0x8C, 0x06, 0xB7, 0x0E, 0xA0, 0xB9, 0x0A, 0xA2, 0xB9, 0x0E, 0xB8, + 0x2A, 0x00, 0x1E, 0x50, 0xB8, 0x00, 0x00, 0x52, 0x50, 0xB8, 0x36, 0x00, 0x50, 0xE8, 0x99, 0xFB, + 0xB8, 0x01, 0x00, 0x50, 0xB8, 0xA2, 0x0E, 0x1E, 0x50, 0xB8, 0x06, 0x00, 0x1E, 0x50, 0xFF, 0x1E, + 0xB5, 0x0E, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xC6, 0x06, 0xB8, 0x0A, 0x00, 0xE8, 0xB0, 0xFF, 0xFF, + 0x36, 0x33, 0x00, 0xB8, 0x50, 0x00, 0x0E, 0x50, 0xB8, 0xB2, 0x0A, 0x1E, 0x50, 0xE8, 0x56, 0xFE, + 0xA3, 0x06, 0x00, 0xFF, 0x36, 0xB2, 0x0A, 0xB8, 0x62, 0x00, 0x0E, 0x50, 0xB8, 0xB4, 0x0A, 0x1E, + 0x50, 0xE8, 0x42, 0xFE, 0xA3, 0x06, 0x00, 0xFF, 0x36, 0xB2, 0x0A, 0xB8, 0x6F, 0x00, 0x0E, 0x50, + 0xB8, 0xB6, 0x0A, 0x1E, 0x50, 0xE8, 0x2E, 0xFE, 0x09, 0xC0, 0x74, 0x03, 0xE9, 0xA5, 0x00, 0x9A, + 0x09, 0x00, 0xEA, 0xFD, 0xC6, 0x06, 0xB8, 0x0A, 0x01, 0xFF, 0x36, 0xB6, 0x0A, 0xB8, 0x68, 0x04, + 0x1E, 0x50, 0xE8, 0x93, 0xFB, 0xB8, 0x68, 0x04, 0x1E, 0x50, 0xB8, 0x70, 0x0A, 0x1E, 0x50, 0xB8, + 0x08, 0x00, 0x50, 0xE8, 0xD4, 0xFC, 0xA3, 0xB0, 0x0A, 0x80, 0x3E, 0x70, 0x0A, 0xFE, 0x75, 0x25, + 0x83, 0x3E, 0x71, 0x0A, 0x04, 0x75, 0x1E, 0x80, 0x3E, 0x77, 0x0A, 0xFF, 0x75, 0x17, 0xA1, 0x73, + 0x0A, 0xB1, 0x03, 0xD3, 0xE8, 0xA3, 0x02, 0x00, 0xB9, 0x50, 0x00, 0x2B, 0xC8, 0xD1, 0xE9, 0x89, + 0x0E, 0x04, 0x00, 0xEB, 0x18, 0xC7, 0x06, 0x04, 0x00, 0x14, 0x00, 0xC7, 0x06, 0x02, 0x00, 0x28, + 0x00, 0xFF, 0x36, 0xB6, 0x0A, 0xB8, 0x68, 0x04, 0x1E, 0x50, 0xE8, 0x3B, 0xFB, 0xC7, 0x06, 0x00, + 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x3D, 0xC7, 0x00, 0x77, 0x29, 0xB9, 0x68, 0x04, 0x1E, 0x51, + 0xB9, 0x50, 0x00, 0xF7, 0xE1, 0x8B, 0x36, 0x04, 0x00, 0x03, 0xF0, 0x2E, 0xC4, 0x1E, 0xA0, 0x00, + 0x8D, 0x00, 0x06, 0x50, 0xFF, 0x36, 0x02, 0x00, 0xE8, 0x5F, 0xFC, 0xA3, 0xB0, 0x0A, 0xFF, 0x06, + 0x00, 0x00, 0x75, 0xCF, 0x83, 0x3E, 0x06, 0x00, 0x00, 0x75, 0x30, 0xA0, 0xB8, 0x0A, 0xD0, 0xD8, + 0x72, 0x0C, 0xB8, 0x88, 0x00, 0x0E, 0x50, 0xB8, 0x12, 0x00, 0x50, 0xE8, 0x98, 0x00, 0xFF, 0x36, + 0xB4, 0x0A, 0xB8, 0x68, 0x04, 0x1E, 0x50, 0xE8, 0xDE, 0xFA, 0xB8, 0x68, 0x04, 0x1E, 0x50, 0xE8, + 0x13, 0xFE, 0x83, 0x3E, 0x06, 0x00, 0x00, 0x75, 0x02, 0x5D, 0xC3, 0xE8, 0x06, 0xFA, 0xE9, 0xD6, + 0xFE, 0x1E, 0x2E, 0x8E, 0x1E, 0x9A, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x08, 0xA3, 0x18, 0x00, + 0x8C, 0x06, 0x1A, 0x00, 0x2E, 0xC4, 0x1E, 0x9C, 0x00, 0x26, 0xC4, 0x47, 0x78, 0xA3, 0x1C, 0x00, + 0x8C, 0x06, 0x1E, 0x00, 0xB8, 0x02, 0x00, 0x2E, 0xC4, 0x1E, 0x9C, 0x00, 0x26, 0x89, 0x47, 0x78, + 0x26, 0x8C, 0x4F, 0x7A, 0xE8, 0x9D, 0xFE, 0xA0, 0xB8, 0x0A, 0xD0, 0xD8, 0x72, 0x05, 0x9A, 0x09, + 0x00, 0xEA, 0xFD, 0xC4, 0x06, 0x1C, 0x00, 0x06, 0x2E, 0xC4, 0x1E, 0x9C, 0x00, 0x26, 0x89, 0x47, + 0x78, 0x5A, 0x26, 0x89, 0x57, 0x7A, 0xB0, 0x0F, 0x50, 0xFF, 0x36, 0x0E, 0x00, 0xFF, 0x36, 0x0C, + 0x00, 0xB8, 0x02, 0x00, 0x50, 0xB8, 0x21, 0x43, 0x50, 0xFF, 0x36, 0xB9, 0x0A, 0xFF, 0x1E, 0x26, + 0x00, 0x5D, 0x1F, 0xCA, 0x04, 0x00, 0x55, 0x8B, 0xEC, 0x8B, 0x4E, 0x04, 0x8E, 0x46, 0x08, 0x8B, + 0x76, 0x06, 0x26, 0x8A, 0x04, 0x46, 0xBB, 0x03, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xE2, 0xF3, 0x5D, + 0xC2, 0x06, 0x00, 0xBA, 0x07, 0x04, 0xB0, 0x00, 0xEE, 0xB8, 0x02, 0x00, 0xCD, 0x10, 0xC3, 0x55, + 0x0B, 0xFF, 0x75, 0x1D, 0x3B, 0xCA, 0x76, 0x09, 0xF7, 0xF1, 0x33, 0xF6, 0x8B, 0xFA, 0x33, 0xD2, + 0xCB, 0x8B, 0xF8, 0x8B, 0xC2, 0x33, 0xD2, 0xF7, 0xF1, 0x97, 0xF7, 0xF1, 0x87, 0xD7, 0x33, 0xF6, + 0xCB, 0x55, 0x8B, 0xE9, 0x8B, 0xDF, 0x33, 0xF6, 0x8B, 0xFE, 0xB9, 0x20, 0x00, 0xD1, 0xE7, 0xD1, + 0xD6, 0xD1, 0xE0, 0xD1, 0xD2, 0x83, 0xD7, 0x00, 0x2B, 0xFD, 0x1B, 0xF3, 0x40, 0x73, 0x05, 0x03, + 0xFD, 0x13, 0xF3, 0x48, 0xE2, 0xE7, 0x5D, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3B, 0xC5, +}; + +#endif // CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H diff --git a/ccos_format.c b/ccos_format.c index e47047f..88aec1e 100644 --- a/ccos_format.c +++ b/ccos_format.c @@ -1,6 +1,7 @@ #include "ccos_format.h" -#include "ccos_format_data.h" +#include "ccos_boot_data.h" +#include "ccos_boot_data.h" #include "common.h" #include "ccos_context.h" #include "ccos_structure.h" @@ -12,6 +13,8 @@ #include #include +#define SECTOR(disk_ptr, id) ((void*)(disk_ptr)->data + (id) * (disk_ptr)->sector_size) + typedef struct { uint16_t sector; uint16_t count; @@ -86,8 +89,7 @@ static bitmask_info_t calculate_bitmask_info(uint16_t sector_size, size_t disk_s static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk, bitmask_info_t info) { // Initialize empty bitmask. for (size_t i = 0; i < info.count; i++) { - const size_t sector_offset = (info.sector + i) * disk->sector_size; - ccos_bitmask_t* bitmask = (ccos_bitmask_t*)&disk->data[sector_offset]; + ccos_bitmask_t* bitmask = (ccos_bitmask_t*)SECTOR(disk, info.sector + i); memset(bitmask, 0x00, disk->sector_size); @@ -135,8 +137,7 @@ static ccos_date_t get_current_date() { static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { uint16_t id = disk->superblock_id; - const size_t sector_offset = id * disk->sector_size; - ccos_inode_t* root_dir = (ccos_inode_t*)&disk->data[sector_offset]; + ccos_inode_t* root_dir = (ccos_inode_t*)SECTOR(disk, id); memset(root_dir, 0x00, disk->sector_size); @@ -179,7 +180,7 @@ static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_lis update_inode_checksums((ccfs_handle)disk, root_dir); - ccos_block_header_t* superblock_entry = (ccos_block_header_t*)get_inode((ccfs_handle)disk, superblock_entry_block, disk->data); + ccos_block_header_t* superblock_entry = (ccos_block_header_t*)SECTOR(disk, superblock_entry_block); memset(superblock_entry, 0x00, disk->sector_size); superblock_entry->file_id = id; superblock_entry->file_fragment_index = 0; @@ -188,44 +189,45 @@ static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_lis mark_block((ccfs_handle)disk, bitmask_list, superblock_entry_block, 1); } -static void write_boot_code(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { - // TODO: Support GRiDCase. - const uint8_t* boot_code = COMPASS_BOOT_CODE; +static void write_boot_code(ccos_disk_t* disk, disk_format_t format, ccos_bitmask_list_t* bitmask_list) { + const uint8_t* boot_code = format == CCOS_DISK_FORMAT_GRIDCASE ? GRIDCASE_BOOT_CODE : COMPASS_BOOT_CODE; - size_t pages = sizeof(COMPASS_BOOT_CODE) / disk->sector_size; - size_t offset = sizeof(ZERO_PAGE) / disk->sector_size; + size_t pages = BOOT_CODE_SIZE / disk->sector_size; + size_t offset = sizeof(ccos_boot_sector_t) / disk->sector_size; for (size_t i = 0; i < pages; i++) { - memcpy(disk->data + (offset + i) * disk->sector_size, COMPASS_BOOT_CODE + i * disk->sector_size, disk->sector_size); + memcpy(SECTOR(disk, offset + i), boot_code + i * disk->sector_size, disk->sector_size); mark_block((ccfs_handle)disk, bitmask_list, offset + i, 1); } } -static void write_zero_page(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { - size_t pages = sizeof(ZERO_PAGE) / disk->sector_size; +static void write_boot_sector(ccos_disk_t* disk, disk_format_t format, ccos_bitmask_list_t* bitmask_list) { + ccos_boot_sector_t boot_sector = (ccos_boot_sector_t) { + .superblock_fid = disk->superblock_id, + .bitmap_fid = disk->bitmap_block_id, + }; + + if (format == CCOS_DISK_FORMAT_GRIDCASE) { + memcpy(boot_sector.header, GRIDCASE_BOOT_SECTOR_HEADER, BOOT_SECTOR_HEADER_SIZE); + memcpy(boot_sector.boot_code, GRIDCASE_BOOT_SECTOR_CODE, BOOT_SECTOR_CODE_SIZE); + } else { + memcpy(boot_sector.header, COMPASS_BOOT_SECTOR_HEADER, BOOT_SECTOR_HEADER_SIZE); + } + + size_t pages = sizeof(ccos_boot_sector_t) / disk->sector_size; for (size_t i = 0; i < pages; i++) { - memcpy(disk->data + i * disk->sector_size, ZERO_PAGE + i * disk->sector_size, disk->sector_size); + memcpy(SECTOR(disk, i), &boot_sector + i * disk->sector_size, disk->sector_size); mark_block((ccfs_handle)disk, bitmask_list, i, 1); } - - // InitializeMedia~Run~ in GRiD-OS 3.1.0 does not initialize these fields - // because it thinks the superblock will be located by the disk status. - // - // In our case, there is no real disk, so the sector numbers must be saved in the image itself. - *(uint16_t*)(disk->data + CCOS_SUPERBLOCK_ADDR_OFFSET) = disk->superblock_id; - *(uint16_t*)(disk->data + CCOS_BITMASK_ADDR_OFFSET) = disk->bitmap_block_id; } -int ccos_new_disk_image(uint16_t sector_size, size_t disk_size, ccos_disk_t* output) { - if (sector_size != 256 && sector_size != 512) { - TRACE("Format image: invalid sector size"); +int ccos_new_disk_image(disk_format_t format, size_t disk_size, ccos_disk_t* output) { + if (disk_size % 512 != 0) { + TRACE("Format image: image size %zu is not a multiple of 512", disk_size); return EINVAL; } - if (disk_size % sector_size != 0) { - TRACE("Format image: image size %zu is not a multiple of sector size %zu", disk_size, sector_size); - return EINVAL; - } + uint16_t sector_size = format == CCOS_DISK_FORMAT_BUBMEM ? 256 : 512; uint8_t* data = new_empty_image(sector_size, disk_size); if (data == NULL) { @@ -248,8 +250,9 @@ int ccos_new_disk_image(uint16_t sector_size, size_t disk_size, ccos_disk_t* out ccos_bitmask_list_t bitmask_list = init_bitmask(&disk, bitmask); write_superblock(&disk, &bitmask_list); - write_boot_code(&disk, &bitmask_list); - write_zero_page(&disk, &bitmask_list); + + write_boot_sector(&disk, format, &bitmask_list); + write_boot_code(&disk, format, &bitmask_list); *output = disk; diff --git a/ccos_format.h b/ccos_format.h index f7a5bc0..c9eabdf 100644 --- a/ccos_format.h +++ b/ccos_format.h @@ -6,15 +6,21 @@ #include #include +typedef enum { + CCOS_DISK_FORMAT_COMPASS, + CCOS_DISK_FORMAT_BUBMEM, + CCOS_DISK_FORMAT_GRIDCASE, +} disk_format_t; + /** * @brief Creates a new empty CCOS disk image. * - * @param[in] sector_size The sector size in bytes. Supported values: 256 or 512. - * @param[in] bytes Total size of the image in bytes. Must be a multiple of sector_size. - * @param[out] output Disk image output. + * @param[in] format The disk format to use (e.g., DISK_FORMAT_COMPASS). + * @param[in] disk_size Total size of the image in bytes, should be a multiple of 512. + * @param[out] output Pointer to the resulting disk image structure. * * @return 0 on success, or an error code. */ -int ccos_new_disk_image(uint16_t sector_size, size_t bytes, ccos_disk_t* output); +int ccos_new_disk_image(disk_format_t format, size_t disk_size, ccos_disk_t* output); #endif // CCOS_DISK_TOOL_CCOS_FORMAT_H diff --git a/ccos_format_data.h b/ccos_format_data.h deleted file mode 100644 index 2cedf73..0000000 --- a/ccos_format_data.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H -#define CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H - -#include -#include - -const uint8_t ZERO_PAGE[512] = { - 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x21, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -const uint8_t COMPASS_BOOT_CODE[2048] = { - 0x9A, 0x42, 0x07, 0x01, 0x20, 0x55, 0xB8, 0x80, 0x20, 0x8E, 0xD8, 0xBB, 0x08, 0x00, 0x58, 0x59, - 0x89, 0x0F, 0x89, 0x47, 0x02, 0xEB, 0xE9, 0x55, 0x43, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, - 0x6F, 0x6F, 0x74, 0x3A, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, - 0x72, 0x0D, 0x0A, 0x43, 0x43, 0x4F, 0x53, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x66, 0x6F, 0x75, 0x6E, - 0x64, 0x0D, 0x0A, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, - 0x72, 0x20, 0x69, 0x6E, 0x20, 0x43, 0x43, 0x4F, 0x53, 0x0D, 0x0A, 0x11, 0x50, 0x72, 0x6F, 0x67, - 0x72, 0x61, 0x6D, 0x73, 0x7E, 0x53, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x7E, 0x0C, 0x43, 0x43, - 0x4F, 0x53, 0x7E, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x7E, 0x18, 0x53, 0x63, 0x72, 0x65, 0x65, - 0x6E, 0x2E, 0x49, 0x6E, 0x69, 0x74, 0x7E, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x49, 0x6D, 0x61, - 0x67, 0x65, 0x7E, 0x55, 0x80, 0x20, 0x00, 0x00, 0x40, 0x00, 0x55, 0x8B, 0xEC, 0xB8, 0x08, 0x00, - 0x0E, 0x50, 0xB8, 0x0D, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0x8B, 0x1E, 0x00, 0x00, 0x4B, - 0xD1, 0xE3, 0x2E, 0xFF, 0xA7, 0xA7, 0x00, 0xAD, 0x00, 0xB7, 0x00, 0xC1, 0x00, 0xB8, 0x15, 0x00, - 0x0E, 0x50, 0xB8, 0x0E, 0x00, 0xEB, 0x12, 0xB8, 0x23, 0x00, 0x0E, 0x50, 0xB8, 0x10, 0x00, 0xEB, - 0x08, 0xB8, 0x33, 0x00, 0x0E, 0x50, 0xB8, 0x18, 0x00, 0x50, 0x9A, 0x06, 0x00, 0xEF, 0xFF, 0xB8, - 0xE8, 0x03, 0x50, 0x9A, 0xD3, 0x00, 0xEF, 0xFF, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB0, 0x00, 0xBF, - 0x99, 0x0E, 0xB9, 0x13, 0x00, 0x1E, 0x07, 0xFC, 0xF2, 0xAA, 0xA0, 0xB0, 0x0E, 0xA2, 0xA7, 0x0E, - 0xC4, 0x46, 0x0A, 0xA3, 0x9B, 0x0E, 0x8C, 0x06, 0x9D, 0x0E, 0x8B, 0x46, 0x04, 0xA3, 0xA3, 0x0E, - 0x8B, 0x46, 0x06, 0x8B, 0x56, 0x08, 0xA3, 0x9F, 0x0E, 0x89, 0x16, 0xA1, 0x0E, 0x5D, 0xC2, 0x0A, - 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x46, 0x04, 0x06, 0x50, 0x8B, 0x46, 0x08, 0xBA, 0x00, 0x00, 0x03, - 0x06, 0x0C, 0x00, 0x13, 0x16, 0x0E, 0x00, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0xAA, 0xFF, - 0xB8, 0x04, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x6C, 0x0A, 0x1E, 0x50, 0xFF, 0x1E, - 0xAC, 0x0E, 0xA1, 0x6C, 0x0A, 0x5D, 0xC2, 0x06, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, 0x04, 0x8D, - 0x47, 0x04, 0xA3, 0x72, 0x0A, 0x8C, 0x06, 0x74, 0x0A, 0xC4, 0x5E, 0x04, 0xB8, 0x00, 0x00, 0x26, - 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x87, 0x06, 0x04, 0x26, 0xC7, 0x07, 0x01, 0x00, 0x26, 0xC7, - 0x47, 0x02, 0x00, 0x00, 0xC4, 0x1E, 0x72, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, 0x6E, 0x0A, 0x8C, - 0x06, 0x70, 0x0A, 0x89, 0xC3, 0x8B, 0x4E, 0x08, 0x26, 0x89, 0x4F, 0x06, 0x5D, 0xC2, 0x06, 0x00, - 0x55, 0x8B, 0xEC, 0x83, 0x7E, 0x04, 0x00, 0x75, 0x08, 0xA1, 0x24, 0x00, 0x2D, 0xD4, 0x00, 0xEB, - 0x06, 0xA1, 0x24, 0x00, 0x83, 0xE8, 0x0C, 0xD1, 0xE8, 0x5D, 0xC2, 0x02, 0x00, 0x55, 0x8B, 0xEC, - 0xB8, 0x00, 0x00, 0x50, 0xE8, 0xD9, 0xFF, 0xA3, 0x76, 0x0A, 0xC4, 0x5E, 0x04, 0x8D, 0x4F, 0x04, - 0x89, 0x0E, 0x86, 0x0A, 0x8C, 0x06, 0x88, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x8B, 0x87, 0x04, 0x04, - 0x26, 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x24, 0x00, 0xBF, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x7B, - 0x20, 0xA3, 0x7A, 0x0A, 0x3B, 0x06, 0x76, 0x0A, 0x73, 0x0D, 0xA3, 0x7C, 0x0A, 0xC4, 0x1E, 0x86, - 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xEB, 0x1E, 0xA1, 0x7A, 0x0A, 0x2B, 0x06, 0x76, 0x0A, 0x50, 0xB9, - 0x01, 0x00, 0x51, 0xE8, 0x8A, 0xFF, 0x89, 0xC1, 0x58, 0x31, 0xD2, 0xF7, 0xF1, 0x89, 0x16, 0x7C, - 0x0A, 0xC4, 0x06, 0x86, 0x0A, 0xA3, 0x7E, 0x0A, 0x8C, 0x06, 0x80, 0x0A, 0x83, 0x3E, 0x7C, 0x0A, - 0x00, 0x75, 0x5A, 0xC4, 0x06, 0x7E, 0x0A, 0xA3, 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xA1, 0x76, - 0x0A, 0x3B, 0x06, 0x7A, 0x0A, 0x75, 0x0F, 0xC4, 0x1E, 0x86, 0x0A, 0x8D, 0x87, 0xCC, 0x00, 0xA3, - 0x82, 0x0A, 0x8C, 0x06, 0x84, 0x0A, 0xC4, 0x1E, 0x82, 0x0A, 0x26, 0xFF, 0x77, 0x06, 0xC4, 0x5E, - 0x04, 0x8D, 0x47, 0x04, 0x06, 0x50, 0xE8, 0xB8, 0xFE, 0xA3, 0x78, 0x0A, 0x09, 0xC0, 0x75, 0x37, - 0x83, 0x3E, 0x7A, 0x0A, 0x00, 0x75, 0x16, 0xC4, 0x1E, 0x86, 0x0A, 0x26, 0x8B, 0x47, 0x04, 0x26, - 0x8B, 0x57, 0x06, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0x26, 0x89, 0x57, 0x02, 0x8B, 0x36, 0x7C, - 0x0A, 0xD1, 0xE6, 0xC4, 0x1E, 0x7E, 0x0A, 0x26, 0xFF, 0x70, 0x0C, 0xC4, 0x5E, 0x04, 0x8D, 0x87, - 0x04, 0x02, 0x06, 0x50, 0xE8, 0x7A, 0xFE, 0x5D, 0xC2, 0x04, 0x00, 0x55, 0x8B, 0xEC, 0xC4, 0x5E, - 0x0A, 0x8D, 0x87, 0x04, 0x02, 0xA3, 0x92, 0x0A, 0x8C, 0x06, 0x94, 0x0A, 0xC7, 0x06, 0x8E, 0x0A, - 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0x97, 0x06, 0x04, 0x26, - 0x3B, 0x57, 0x02, 0x75, 0x03, 0x26, 0x3B, 0x07, 0xB0, 0xFF, 0x74, 0x01, 0x40, 0xA2, 0xB1, 0x0E, - 0xA1, 0x8E, 0x0A, 0x3B, 0x46, 0x04, 0x72, 0x03, 0xE9, 0xE5, 0x00, 0xA0, 0xB1, 0x0E, 0xD0, 0xD8, - 0x73, 0x03, 0xE9, 0xDB, 0x00, 0x8B, 0x0E, 0x24, 0x00, 0xBA, 0x00, 0x00, 0xC4, 0x5E, 0x0A, 0x26, - 0x8B, 0x87, 0x04, 0x04, 0x26, 0x8B, 0xBF, 0x06, 0x04, 0x87, 0xFA, 0x51, 0x57, 0x9A, 0x00, 0x00, - 0x7B, 0x20, 0x89, 0x3E, 0x8A, 0x0A, 0x5B, 0x58, 0x2B, 0xC7, 0xA3, 0x8C, 0x0A, 0x09, 0xFF, 0x75, - 0x0F, 0xC4, 0x46, 0x0A, 0x06, 0x50, 0xE8, 0x94, 0xFE, 0x09, 0xC0, 0x74, 0x03, 0xE9, 0xA0, 0x00, - 0x8B, 0x0E, 0x8C, 0x0A, 0xA1, 0x8E, 0x0A, 0x03, 0xC8, 0x8B, 0x46, 0x04, 0x3B, 0xC8, 0x76, 0x07, - 0x2B, 0x06, 0x8E, 0x0A, 0xA3, 0x8C, 0x0A, 0xC4, 0x5E, 0x0A, 0x26, 0x8B, 0x87, 0x04, 0x04, 0x26, - 0x8B, 0x97, 0x06, 0x04, 0x8B, 0x0E, 0x8C, 0x0A, 0xBF, 0x00, 0x00, 0x03, 0xC8, 0x13, 0xFA, 0x26, - 0x8B, 0x37, 0x26, 0x8B, 0x47, 0x02, 0x3B, 0xF8, 0x75, 0x02, 0x3B, 0xCE, 0x76, 0x15, 0x26, 0x2B, - 0xB7, 0x04, 0x04, 0x26, 0x1B, 0x87, 0x06, 0x04, 0x89, 0x36, 0x90, 0x0A, 0xC6, 0x06, 0xB1, 0x0E, - 0x01, 0xEB, 0x06, 0xA1, 0x8C, 0x0A, 0xA3, 0x90, 0x0A, 0xC4, 0x1E, 0x92, 0x0A, 0x8B, 0x36, 0x8A, - 0x0A, 0x8D, 0x70, 0x04, 0x06, 0xC4, 0x5E, 0x06, 0x8B, 0x3E, 0x8E, 0x0A, 0x8D, 0x39, 0x8B, 0x0E, - 0x90, 0x0A, 0x1E, 0x8E, 0x9E, 0xFE, 0xFF, 0xFC, 0xF2, 0xA4, 0x1F, 0x59, 0xA1, 0x90, 0x0A, 0x01, - 0x06, 0x8E, 0x0A, 0xC4, 0x5E, 0x0A, 0xBA, 0x00, 0x00, 0x26, 0x03, 0x87, 0x04, 0x04, 0x26, 0x13, - 0x97, 0x06, 0x04, 0x26, 0x89, 0x87, 0x04, 0x04, 0x26, 0x89, 0x97, 0x06, 0x04, 0xE9, 0x10, 0xFF, - 0xA1, 0x8E, 0x0A, 0x5D, 0xC2, 0x0A, 0x00, 0x55, 0x8B, 0xEC, 0xA1, 0x00, 0x00, 0x09, 0xC0, 0x75, - 0x2D, 0xFF, 0x76, 0x0C, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xE8, 0x6D, 0xFD, 0xB8, 0x58, 0x00, 0x1E, - 0x50, 0xB8, 0xEF, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0xAE, 0xFE, 0xA3, 0x98, 0x0A, - 0x09, 0xC0, 0x74, 0x07, 0x80, 0x3E, 0xEF, 0x0E, 0xFF, 0x75, 0x05, 0xB8, 0x02, 0x00, 0xEB, 0x6B, - 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0x96, 0x0A, 0x1E, 0x50, 0xB8, 0x02, 0x00, 0x50, 0xE8, 0x8A, - 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB2, 0x0E, 0x1E, 0x50, 0xB8, 0x01, - 0x00, 0x50, 0xE8, 0x76, 0xFE, 0xA3, 0x98, 0x0A, 0xB8, 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xB3, 0x0E, - 0x1E, 0x50, 0xA0, 0xB2, 0x0E, 0xB4, 0x00, 0x50, 0xE8, 0x60, 0xFE, 0xA3, 0x98, 0x0A, 0xC4, 0x5E, - 0x08, 0xA0, 0xB2, 0x0E, 0x26, 0x38, 0x07, 0x75, 0x26, 0xB9, 0xB3, 0x0E, 0x1E, 0x51, 0x8D, 0x4F, - 0x01, 0x06, 0x51, 0xB4, 0x00, 0x50, 0x9A, 0xEC, 0x00, 0xEF, 0xFF, 0xD0, 0xD8, 0x73, 0x10, 0xA1, - 0x96, 0x0A, 0xC4, 0x5E, 0x04, 0x26, 0x89, 0x07, 0xB8, 0x00, 0x00, 0x5D, 0xC2, 0x0A, 0x00, 0xB8, - 0x58, 0x00, 0x1E, 0x50, 0xB8, 0xF0, 0x0E, 0x1E, 0x50, 0xB8, 0x01, 0x00, 0x50, 0xE8, 0x1B, 0xFE, - 0xA3, 0x98, 0x0A, 0xE9, 0x56, 0xFF, 0x55, 0x8B, 0xEC, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xB8, 0x18, - 0x00, 0x1E, 0x50, 0xB8, 0x0A, 0x00, 0x50, 0xE8, 0x01, 0xFE, 0xA3, 0x9C, 0x0A, 0xC7, 0x06, 0x9E, - 0x0A, 0x00, 0x00, 0xC7, 0x06, 0x9C, 0x0A, 0xEC, 0x03, 0xB8, 0xEC, 0x03, 0x39, 0x06, 0x9C, 0x0A, - 0x75, 0x1E, 0xB9, 0x60, 0x04, 0x1E, 0x51, 0xC4, 0x1E, 0x1A, 0x00, 0x8B, 0x36, 0x9E, 0x0A, 0x8D, - 0x08, 0x06, 0x51, 0x50, 0xE8, 0xD4, 0xFD, 0xA3, 0x9C, 0x0A, 0x01, 0x06, 0x9E, 0x0A, 0xEB, 0xD9, - 0xB8, 0x1A, 0x00, 0x1E, 0x50, 0xB8, 0x08, 0x00, 0x50, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x50, 0xC4, - 0x06, 0x1A, 0x00, 0x06, 0x50, 0xFF, 0x36, 0x9E, 0x0A, 0x9A, 0xF1, 0x00, 0xEF, 0xFF, 0x59, 0x03, - 0xC1, 0x3B, 0x06, 0x18, 0x00, 0x74, 0x06, 0xC7, 0x06, 0x00, 0x00, 0x03, 0x00, 0x5D, 0xC3, 0x55, - 0x8B, 0xEC, 0xB0, 0x00, 0xA2, 0x2F, 0x00, 0xA2, 0x56, 0x00, 0xA1, 0x76, 0x08, 0x09, 0xC0, 0x74, - 0x24, 0xA3, 0x50, 0x00, 0xA1, 0x78, 0x08, 0xA3, 0x52, 0x00, 0x8B, 0x0E, 0x7A, 0x08, 0x89, 0x0E, - 0x54, 0x00, 0x8A, 0x16, 0x7E, 0x08, 0x88, 0x16, 0x57, 0x00, 0xF7, 0xE1, 0xF7, 0x26, 0x7C, 0x08, - 0xA3, 0x26, 0x00, 0xEB, 0x17, 0xC7, 0x06, 0x52, 0x00, 0x09, 0x00, 0xC7, 0x06, 0x54, 0x00, 0x02, - 0x00, 0xC6, 0x06, 0x57, 0x00, 0x01, 0xC7, 0x06, 0x26, 0x00, 0xD0, 0x02, 0xB8, 0x22, 0x00, 0x1E, - 0x50, 0xB8, 0xFF, 0xFF, 0x89, 0xC2, 0x52, 0x50, 0xFF, 0x36, 0x22, 0x00, 0xE8, 0x7B, 0xFB, 0xC6, - 0x06, 0xA5, 0x0E, 0x01, 0xB8, 0x05, 0x00, 0x50, 0xB8, 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0xA0, 0x0A, - 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0xB8, 0x00, 0x00, 0x89, 0xC2, - 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xC6, 0x06, 0xF1, 0x0E, 0x01, 0xC6, 0x06, 0xB0, 0x0E, - 0x04, 0xBF, 0xEF, 0xFF, 0xB9, 0x24, 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0x80, - 0x3E, 0xB0, 0x0A, 0x62, 0x75, 0x18, 0xC6, 0x06, 0xB0, 0x0E, 0xFF, 0xBF, 0xEF, 0xFF, 0xB9, 0x1A, - 0x00, 0x89, 0x0E, 0xAC, 0x0E, 0x89, 0x3E, 0xAE, 0x0E, 0xA2, 0xF1, 0x0E, 0xEB, 0x1A, 0x80, 0x3E, - 0xB0, 0x0A, 0x63, 0x75, 0x07, 0xC6, 0x06, 0xB0, 0x0E, 0x06, 0xEB, 0x0C, 0x80, 0x3E, 0xB0, 0x0A, - 0x77, 0x74, 0x05, 0xC6, 0x06, 0xB0, 0x0E, 0x05, 0xB8, 0x22, 0x00, 0x1E, 0x50, 0xB8, 0x00, 0x00, - 0x89, 0xC2, 0x52, 0x50, 0xB8, 0x36, 0x00, 0x50, 0xE8, 0xEF, 0xFA, 0xB8, 0x01, 0x00, 0x50, 0xB8, - 0x99, 0x0E, 0x1E, 0x50, 0xB8, 0x00, 0x00, 0x1E, 0x50, 0xFF, 0x1E, 0xAC, 0x0E, 0x83, 0x3E, 0x00, - 0x00, 0x00, 0x74, 0x02, 0x5D, 0xC3, 0xB8, 0x00, 0x02, 0x31, 0xD2, 0xF7, 0x36, 0x22, 0x00, 0xA3, - 0xA2, 0x0A, 0xB8, 0x68, 0x08, 0xA3, 0xA4, 0x0A, 0x8C, 0x1E, 0xA6, 0x0A, 0xC6, 0x06, 0xF2, 0x0E, - 0x00, 0xA1, 0xA2, 0x0A, 0x48, 0x8A, 0x0E, 0xF2, 0x0E, 0xB5, 0x00, 0x3B, 0xC8, 0x77, 0x29, 0x83, - 0x3E, 0x00, 0x00, 0x00, 0x75, 0x1C, 0xB8, 0x00, 0x00, 0x50, 0x8B, 0x16, 0x22, 0x00, 0x89, 0xD0, - 0xF7, 0xE1, 0x89, 0xC6, 0xC4, 0x1E, 0xA4, 0x0A, 0x8D, 0x00, 0x06, 0x50, 0xE8, 0xC2, 0xFA, 0xA3, - 0x00, 0x00, 0xFE, 0x06, 0xF2, 0x0E, 0x75, 0xC9, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x74, 0x02, 0x5D, - 0xC3, 0xA0, 0xF1, 0x0E, 0xD0, 0xD8, 0x73, 0x0B, 0x81, 0x3E, 0x26, 0x00, 0x40, 0x1F, 0x73, 0x03, - 0xE8, 0x8C, 0xFE, 0x81, 0x3E, 0x24, 0x0A, 0xAA, 0x55, 0x75, 0x1D, 0xA1, 0x08, 0x00, 0x8B, 0x16, - 0x0A, 0x00, 0xA3, 0x0C, 0x00, 0x89, 0x16, 0x0E, 0x00, 0xB8, 0x00, 0x00, 0x50, 0xB8, 0x68, 0x08, - 0x1E, 0x50, 0xE8, 0x7C, 0xFA, 0xA3, 0x00, 0x00, 0xA1, 0x88, 0x08, 0x09, 0xC0, 0x74, 0x03, 0xA3, - 0x2B, 0x00, 0x5D, 0xC3, 0x55, 0x8B, 0xEC, 0x9A, 0x15, 0x00, 0xEF, 0xFF, 0x89, 0x1E, 0x14, 0x00, - 0x8C, 0x06, 0x16, 0x00, 0x26, 0x8A, 0x47, 0x16, 0xA2, 0xB0, 0x0A, 0xE8, 0xBA, 0xFE, 0xFF, 0x36, - 0x2B, 0x00, 0xB8, 0x4B, 0x00, 0x0E, 0x50, 0xB8, 0xAA, 0x0A, 0x1E, 0x50, 0xE8, 0xF8, 0xFC, 0xA3, - 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x5D, 0x00, 0x0E, 0x50, 0xB8, 0xAC, 0x0A, 0x1E, 0x50, - 0xE8, 0xE4, 0xFC, 0xA3, 0x00, 0x00, 0xFF, 0x36, 0xAA, 0x0A, 0xB8, 0x6A, 0x00, 0x0E, 0x50, 0xB8, - 0xAE, 0x0A, 0x1E, 0x50, 0xE8, 0xD0, 0xFC, 0x09, 0xC0, 0x75, 0x22, 0xFF, 0x36, 0xAE, 0x0A, 0xB8, - 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x42, 0xFA, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0x2E, 0xC4, 0x06, 0x86, - 0x00, 0x06, 0x50, 0xB8, 0x80, 0x25, 0x50, 0xE8, 0x81, 0xFB, 0xA3, 0xA8, 0x0A, 0x83, 0x3E, 0x00, - 0x00, 0x00, 0x75, 0x18, 0xFF, 0x36, 0xAC, 0x0A, 0xB8, 0x60, 0x04, 0x1E, 0x50, 0xE8, 0x19, 0xFA, - 0xE8, 0x53, 0xFD, 0x83, 0x3E, 0x00, 0x00, 0x00, 0x75, 0x02, 0x5D, 0xC3, 0xE8, 0x4B, 0xF9, 0xE9, - 0x79, 0xFF, 0x1E, 0x2E, 0x8E, 0x1E, 0x84, 0x00, 0x55, 0x8B, 0xEC, 0x89, 0xE0, 0xA3, 0x02, 0x00, - 0x8C, 0xD0, 0xA3, 0x04, 0x00, 0xB8, 0xB1, 0x0A, 0xA3, 0x10, 0x00, 0x8C, 0x1E, 0x12, 0x00, 0xFA, - 0xA1, 0x10, 0x00, 0x8B, 0x16, 0x12, 0x00, 0x05, 0xE8, 0x03, 0x83, 0xE8, 0x0A, 0x89, 0xC4, 0xA1, - 0x12, 0x00, 0x8E, 0xD0, 0xFB, 0xE8, 0x2C, 0xFF, 0xFA, 0xA1, 0x02, 0x00, 0x89, 0xC4, 0xA1, 0x04, - 0x00, 0x8E, 0xD0, 0xFB, 0xFF, 0x36, 0x0E, 0x00, 0xFF, 0x36, 0x0C, 0x00, 0xB8, 0x01, 0x00, 0x50, - 0xB8, 0x21, 0x43, 0x50, 0xFF, 0x1E, 0x1E, 0x00, 0x5D, 0x1F, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x0B, 0xFF, 0x75, 0x1D, 0x3B, 0xCA, 0x76, 0x09, 0xF7, 0xF1, 0x33, 0xF6, 0x8B, 0xFA, 0x33, 0xD2, - 0xCB, 0x8B, 0xF8, 0x8B, 0xC2, 0x33, 0xD2, 0xF7, 0xF1, 0x97, 0xF7, 0xF1, 0x87, 0xD7, 0x33, 0xF6, - 0xCB, 0x55, 0x8B, 0xE9, 0x8B, 0xDF, 0x33, 0xF6, 0x8B, 0xFE, 0xB9, 0x20, 0x00, 0xD1, 0xE7, 0xD1, - 0xD6, 0xD1, 0xE0, 0xD1, 0xD2, 0x83, 0xD7, 0x00, 0x2B, 0xFD, 0x1B, 0xF3, 0x40, 0x73, 0x05, 0x03, - 0xFD, 0x13, 0xF3, 0x48, 0xE2, 0xE7, 0x5D, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x76, 0x65, -}; - -#endif // CCOS_DISK_TOOL_CCOS_FORMAT_DATA_H diff --git a/ccos_structure.h b/ccos_structure.h index 3f0e27a..a1e58d0 100644 --- a/ccos_structure.h +++ b/ccos_structure.h @@ -47,6 +47,42 @@ #define CCOS_DATA_OFFSET sizeof(ccos_block_header_t) +#pragma pack(push, 1) +typedef struct { + uint8_t boot_indicator; + uint8_t begin_head; + uint8_t begin_sector; + uint8_t begin_cylinder; + uint8_t system_indicator; + uint8_t ending_head; + uint8_t ending_sector; + uint8_t ending_cylinder; + uint32_t relative_sector; + uint32_t num_sectors; +} ccos_boot_sector_partition_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct { + uint8_t header[14]; + uint16_t bytes_per_page; + uint16_t pages_per_track; + uint16_t tracks_per_cylinder; + uint16_t num_cylinders; + uint8_t second_side_count; + uint16_t valid_info_flag; + uint8_t dummy[5]; + uint16_t bitmap_fid; + uint16_t superblock_fid; + uint16_t min_dir_pages; + uint16_t log_page_size; + uint8_t boot_code[406]; + uint16_t partition_indicator; + ccos_boot_sector_partition_t partitionTable[4]; + uint16_t last_word_flag; +} ccos_boot_sector_t; +#pragma pack(pop) + #pragma pack(push, 1) typedef struct { uint16_t year; diff --git a/tests/format_test.c b/tests/format_test.c index 4d87d48..169feb8 100644 --- a/tests/format_test.c +++ b/tests/format_test.c @@ -99,7 +99,7 @@ Test(format, floppy_360k) { ccos_disk_t disk; - int ret = ccos_new_disk_image(512, image_size, &disk); + int ret = ccos_new_disk_image(CCOS_DISK_FORMAT_COMPASS, image_size, &disk); cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); uint8_t* expected = load_image("files/floppy 360k/empty.img", image_size); @@ -116,7 +116,7 @@ Test(format, floppy_720k) { ccos_disk_t disk; - int ret = ccos_new_disk_image(512, image_size, &disk); + int ret = ccos_new_disk_image(CCOS_DISK_FORMAT_COMPASS, image_size, &disk); cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); uint8_t* expected = load_image("files/floppy 720k/empty.img", image_size); diff --git a/wrapper.c b/wrapper.c index d9c1667..062b50f 100644 --- a/wrapper.c +++ b/wrapper.c @@ -843,7 +843,8 @@ int create_blank_image(ccfs_handle ctx, char* path, size_t size) { ccos_disk_t disk; - int res = ccos_new_disk_image(ctx->sector_size, size, &disk); + disk_format_t format = ctx->sector_size == 256 ? CCOS_DISK_FORMAT_BUBMEM : CCOS_DISK_FORMAT_COMPASS; + int res = ccos_new_disk_image(format, size, &disk); if (res) { fprintf(stderr, "Failed to create new disk image. Error code: %s\n", strerror(res)); return res; From 04ce24bd5c5b72df28b16c3aeb6d5c3232ae6a91 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 15:30:08 +0100 Subject: [PATCH 08/13] add format test for bubbles --- tests/files/bubbles/empty.img | Bin 0 -> 393216 bytes tests/format_test.c | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 tests/files/bubbles/empty.img diff --git a/tests/files/bubbles/empty.img b/tests/files/bubbles/empty.img new file mode 100644 index 0000000000000000000000000000000000000000..a5a2febfdda781fe9767055fbd3bfb23d4e95d52 GIT binary patch literal 393216 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 D+ZiOo literal 0 HcmV?d00001 diff --git a/tests/format_test.c b/tests/format_test.c index 169feb8..3528b6c 100644 --- a/tests/format_test.c +++ b/tests/format_test.c @@ -77,22 +77,22 @@ static uint8_t* load_image(const char* path, size_t expected_size) { return data; } -// Test(format, bubbles) { -// size_t image_size = 3 * 128 * 1024; +Test(format, bubbles) { + size_t image_size = 3 * 128 * 1024; -// ccos_disk_t disk; + ccos_disk_t disk; -// int ret = ccos_new_disk_image(256, image_size, &disk); -// cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); + int ret = ccos_new_disk_image(CCOS_DISK_FORMAT_BUBMEM, image_size, &disk); + cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); -// uint8_t* expected = load_image("files/bubbles/empty.img", image_size); -// cr_assert_not_null(expected, "Failed to load expected image"); + uint8_t* expected = load_image("files/bubbles/empty.img", image_size); + cr_assert_not_null(expected, "Failed to load expected image"); -// compare_disk_with_ref(&disk, expected); + compare_disk_with_ref(&disk, expected); -// free(disk.data); -// free(expected); -// } + free(disk.data); + free(expected); +} Test(format, floppy_360k) { size_t image_size = 360 * 1024; From 399026887b25909292e1eaee5bcbdb5809e01ccc Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 16:44:02 +0100 Subject: [PATCH 09/13] add format test for 10mb hdd --- tests/files/hdd 10mb/empty.img | Bin 0 -> 10485760 bytes tests/format_test.c | 29 +++++++++++------------------ 2 files changed, 11 insertions(+), 18 deletions(-) create mode 100644 tests/files/hdd 10mb/empty.img diff --git a/tests/files/hdd 10mb/empty.img b/tests/files/hdd 10mb/empty.img new file mode 100644 index 0000000000000000000000000000000000000000..66cc3b481816dbb1545057d42bca2c0f6b857a09 GIT binary patch literal 10485760 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 z{z>+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) zWZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;H zrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VD zfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g z=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7< zUupiEA{qE6*;ktXrbq_+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4)WZ<7+g=D#VDfq#;HrTK4) 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 z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z18;i&>;E?JruV=8Zv$_7|LgxY@TT{_{%-?sdjISHHt?qRzy5CnZ+idh|2FWZ_rLyc z1GP^FGynhq0KxjV7UUveZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI z``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<|G&R&z^4EI w``ZR=`v1SbZNR4g|NGkpZ2JGdziq&#|Nr~j25kEOzrSt3rvLx@+Xig<0KJ>$;{X5v literal 0 HcmV?d00001 diff --git a/tests/format_test.c b/tests/format_test.c index 3528b6c..7b50a6b 100644 --- a/tests/format_test.c +++ b/tests/format_test.c @@ -128,29 +128,22 @@ Test(format, floppy_720k) { free(expected); } -// Test(format, hdd_10mb) { -// ccfs_context_t ctx = { -// .sector_size = 512, -// .superblock_id = 0x121, -// .bitmap_block_id = 0x120, -// }; - -// size_t image_size = 10 * 1024 * 1024; +Test(format, hdd_10mb) { + size_t image_size = 10 * 1024 * 1024; -// uint8_t* buffer = calloc(1, image_size); -// cr_assert_not_null(buffer, "Failed to allocate buffer"); + ccos_disk_t disk; -// int result = format_image(&ctx, buffer, image_size); -// cr_assert_eq(result, 0, "format_image failed"); + int ret = ccos_new_disk_image(CCOS_DISK_FORMAT_COMPASS, image_size, &disk); + cr_assert_eq(ret, 0, "ccos_new_disk_image failed"); -// uint8_t* expected = load_image("files/hdd 10mb/empty.img", image_size); -// cr_assert_not_null(expected, "Failed to load expected image"); + uint8_t* expected = load_image("files/hdd 10mb/empty.img", image_size); + cr_assert_not_null(expected, "Failed to load expected image"); -// compare_images_sector_by_sector(buffer, expected, image_size, ctx.sector_size); + compare_disk_with_ref(&disk, expected); -// free(buffer); -// free(expected); -// } + free(disk.data); + free(expected); +} // Test(format, hdd_20mb) { // ccfs_context_t ctx = { From 5f376d2e41610d45230a1253cc933e2a1e160b3b Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Thu, 15 Jan 2026 16:49:39 +0100 Subject: [PATCH 10/13] select superblock easily --- ccos_format.c | 11 +---------- tests/format_test.c | 24 ------------------------ 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/ccos_format.c b/ccos_format.c index 88aec1e..6cdcdc0 100644 --- a/ccos_format.c +++ b/ccos_format.c @@ -44,19 +44,10 @@ static uint16_t select_superblock(uint16_t sector_size, size_t disk_size) { assert(sector_size == 256 || sector_size == 512); if (sector_size == 256) { - // For bubble disks we always use the default value. return DEFAULT_BUBBLE_SUPERBLOCK; - } else if (disk_size < 1 * 1024 * 1024) { - // For floppy disks we always use the block number from the 2102 floppy firmware. - return DEFAULT_SUPERBLOCK; - } else if (disk_size < 4 * 1024 * 1024) { - // Value selected by analogy. - return 0x510; } else if (disk_size < 10 * 1024 * 1024) { - // Value selected by analogy. - return 0x1010; + return DEFAULT_SUPERBLOCK; } else { - // For big hard drives we always use the block number from the 2101 hard disk firmware. return DEFAULT_HDD_SUPERBLOCK; } } diff --git a/tests/format_test.c b/tests/format_test.c index 7b50a6b..84851dc 100644 --- a/tests/format_test.c +++ b/tests/format_test.c @@ -144,27 +144,3 @@ Test(format, hdd_10mb) { free(disk.data); free(expected); } - -// Test(format, hdd_20mb) { -// ccfs_context_t ctx = { -// .sector_size = 512, -// .superblock_id = 0x121, -// .bitmap_block_id = 0x120, -// }; - -// size_t image_size = 20 * 1024 * 1024; - -// uint8_t* buffer = calloc(1, image_size); -// cr_assert_not_null(buffer, "Failed to allocate buffer"); - -// int result = format_image(&ctx, buffer, image_size); -// cr_assert_eq(result, 0, "format_image failed"); - -// uint8_t* expected = load_image("files/hdd 20mb/empty.img", image_size); -// cr_assert_not_null(expected, "Failed to load expected image"); - -// compare_images_sector_by_sector(buffer, expected, image_size, ctx.sector_size); - -// free(buffer); -// free(expected); -// } From 580f86fae907dccd5d7954b067bd6f2d1c3aef95 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Sun, 18 Jan 2026 00:22:05 +0100 Subject: [PATCH 11/13] just merge ccfs_context_t with ccos_disk_t --- CMakeLists.txt | 1 + ccos_context.h | 23 ----- ccos_disk.h | 15 ++++ ccos_format.c | 32 +++---- ccos_format.h | 2 +- ccos_image.c | 163 +++++++++++++++++----------------- ccos_image.h | 41 +++++---- ccos_private.c | 212 ++++++++++++++++++++++---------------------- ccos_private.h | 56 ++++++------ ccos_structure.c | 4 +- ccos_structure.h | 18 ++-- main.c | 46 +++++----- tests/format_test.c | 2 +- wrapper.c | 144 +++++++++++++++--------------- wrapper.h | 29 +++--- 15 files changed, 391 insertions(+), 397 deletions(-) delete mode 100644 ccos_context.h create mode 100644 ccos_disk.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 71e5cec..7f7a889 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ add_library(ccos_api STATIC ${SOURCE_DIR}/string_utils.c ${SOURCE_DIR}/common.h ${SOURCE_DIR}/common.c + ${SOURCE_DIR}/ccos_disk.h ${SOURCE_DIR}/ccos_image.h ${SOURCE_DIR}/ccos_image.c ${SOURCE_DIR}/ccos_boot_data.h diff --git a/ccos_context.h b/ccos_context.h deleted file mode 100644 index 89c0e7e..0000000 --- a/ccos_context.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CCOS_CONTEXT_H -#define CCOS_CONTEXT_H - -#include -#include - -typedef struct { - uint16_t sector_size; - uint16_t superblock_id; - uint16_t bitmap_block_id; -} ccfs_context_t; - -typedef const ccfs_context_t* ccfs_handle; - -typedef struct { - uint16_t sector_size; - uint16_t superblock_id; - uint16_t bitmap_block_id; - size_t size; - uint8_t* data; -} ccos_disk_t; - -#endif // CCOS_CONTEXT_H diff --git a/ccos_disk.h b/ccos_disk.h new file mode 100644 index 0000000..e64d74f --- /dev/null +++ b/ccos_disk.h @@ -0,0 +1,15 @@ +#ifndef CCOS_CONTEXT_H +#define CCOS_CONTEXT_H + +#include +#include + +typedef struct { + uint16_t sector_size; + uint16_t superblock_fid; + uint16_t bitmap_fid; + size_t size; + uint8_t* data; +} ccos_disk_t; + +#endif // CCOS_CONTEXT_H diff --git a/ccos_format.c b/ccos_format.c index 6cdcdc0..e023295 100644 --- a/ccos_format.c +++ b/ccos_format.c @@ -3,7 +3,7 @@ #include "ccos_boot_data.h" #include "common.h" -#include "ccos_context.h" +#include "ccos_disk.h" #include "ccos_structure.h" #include "ccos_private.h" @@ -93,15 +93,15 @@ static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk, bitmask_info_t info) memset(bitmask_bytes + info.tail_offset, 0xff, info.tail_length); } - update_bitmask_checksum((ccfs_handle)disk, bitmask); + update_bitmask_checksum(disk, bitmask); } // Build list of bitmask blocks. - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks((ccfs_handle)disk, disk->data, disk->size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, disk->data, disk->size); // Mark the bitmask blocks as used in the bitmask itself. for (size_t i = 0; i < info.count; i++) { - mark_block((ccfs_handle)disk, &bitmask_list, info.sector + i, 1); + mark_block(disk, &bitmask_list, info.sector + i, 1); } return bitmask_list; @@ -126,7 +126,7 @@ static ccos_date_t get_current_date() { } static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list) { - uint16_t id = disk->superblock_id; + uint16_t id = disk->superblock_fid; ccos_inode_t* root_dir = (ccos_inode_t*)SECTOR(disk, id); @@ -135,7 +135,7 @@ static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_lis root_dir->header.file_id = id; root_dir->header.file_fragment_index = 0; - root_dir->desc.file_size = get_dir_default_size((ccfs_handle)disk); + root_dir->desc.file_size = get_dir_default_size(disk); root_dir->desc.name_length = 0; memset(root_dir->desc.name, ' ', sizeof(root_dir->desc.name)); @@ -159,17 +159,17 @@ static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_lis root_dir->content_inode_info.block_current = id; root_dir->content_inode_info.block_prev = CCOS_INVALID_BLOCK; - mark_block((ccfs_handle)disk, bitmask_list, id, 1); + mark_block(disk, bitmask_list, id, 1); uint16_t* content_blocks = get_inode_content_blocks(root_dir); - size_t max_content_blocks = get_inode_max_blocks((ccfs_handle)disk); + size_t max_content_blocks = get_inode_max_blocks(disk); memset(content_blocks, 0xFF, max_content_blocks * sizeof(uint16_t)); uint16_t superblock_entry_block = id + 1; content_blocks[0] = superblock_entry_block; - update_inode_checksums((ccfs_handle)disk, root_dir); + update_inode_checksums(disk, root_dir); ccos_block_header_t* superblock_entry = (ccos_block_header_t*)SECTOR(disk, superblock_entry_block); memset(superblock_entry, 0x00, disk->sector_size); @@ -177,7 +177,7 @@ static void write_superblock(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_lis superblock_entry->file_fragment_index = 0; ((uint16_t*)superblock_entry)[2] = CCOS_DIR_LAST_ENTRY_MARKER; - mark_block((ccfs_handle)disk, bitmask_list, superblock_entry_block, 1); + mark_block(disk, bitmask_list, superblock_entry_block, 1); } static void write_boot_code(ccos_disk_t* disk, disk_format_t format, ccos_bitmask_list_t* bitmask_list) { @@ -188,14 +188,14 @@ static void write_boot_code(ccos_disk_t* disk, disk_format_t format, ccos_bitmas for (size_t i = 0; i < pages; i++) { memcpy(SECTOR(disk, offset + i), boot_code + i * disk->sector_size, disk->sector_size); - mark_block((ccfs_handle)disk, bitmask_list, offset + i, 1); + mark_block(disk, bitmask_list, offset + i, 1); } } static void write_boot_sector(ccos_disk_t* disk, disk_format_t format, ccos_bitmask_list_t* bitmask_list) { ccos_boot_sector_t boot_sector = (ccos_boot_sector_t) { - .superblock_fid = disk->superblock_id, - .bitmap_fid = disk->bitmap_block_id, + .superblock_fid = disk->superblock_fid, + .bitmap_fid = disk->bitmap_fid, }; if (format == CCOS_DISK_FORMAT_GRIDCASE) { @@ -208,7 +208,7 @@ static void write_boot_sector(ccos_disk_t* disk, disk_format_t format, ccos_bitm size_t pages = sizeof(ccos_boot_sector_t) / disk->sector_size; for (size_t i = 0; i < pages; i++) { memcpy(SECTOR(disk, i), &boot_sector + i * disk->sector_size, disk->sector_size); - mark_block((ccfs_handle)disk, bitmask_list, i, 1); + mark_block(disk, bitmask_list, i, 1); } } @@ -233,8 +233,8 @@ int ccos_new_disk_image(disk_format_t format, size_t disk_size, ccos_disk_t* out ccos_disk_t disk = { .sector_size = sector_size, - .superblock_id = superblock, - .bitmap_block_id = bitmask.sector, + .superblock_fid = superblock, + .bitmap_fid = bitmask.sector, .size = disk_size, .data = data }; diff --git a/ccos_format.h b/ccos_format.h index c9eabdf..5f5b7ff 100644 --- a/ccos_format.h +++ b/ccos_format.h @@ -1,7 +1,7 @@ #ifndef CCOS_DISK_TOOL_CCOS_FORMAT_H #define CCOS_DISK_TOOL_CCOS_FORMAT_H -#include "ccos_context.h" +#include "ccos_disk.h" #include #include diff --git a/ccos_image.c b/ccos_image.c index 83dc5da..78c7fd8 100644 --- a/ccos_image.c +++ b/ccos_image.c @@ -1,11 +1,12 @@ +#include "common.h" +#include "ccos_image.h" +#include "ccos_private.h" + #include #include #include #include #include -#include "common.h" -#include "ccos_image.h" -#include "ccos_private.h" #define FAT_MBR_END_OF_SECTOR_MARKER 0xAA55 #define OPCODE_NOP 0x90 @@ -54,7 +55,7 @@ version_t ccos_get_file_version(const ccos_inode_t* file) { return version; } -int ccos_set_file_version(ccfs_handle ctx, ccos_inode_t* file, version_t new_version) { +int ccos_set_file_version(ccos_disk_t* disk, ccos_inode_t* file, version_t new_version) { if (is_root_dir(file)) { return -1; } @@ -62,7 +63,7 @@ int ccos_set_file_version(ccfs_handle ctx, ccos_inode_t* file, version_t new_ver file->desc.version_major = new_version.major; file->desc.version_minor = new_version.minor; file->desc.version_patch = new_version.patch; - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); return 0; } @@ -87,22 +88,22 @@ ccos_date_t ccos_get_exp_date(const ccos_inode_t* file) { return file->desc.expiration_date; } -int ccos_set_creation_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date) { - return change_date(ctx, file, new_date, CREATED); +int ccos_set_creation_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date) { + return change_date(disk, file, new_date, CREATED); } -int ccos_set_mod_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date) { - return change_date(ctx, file, new_date, MODIF); +int ccos_set_mod_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date) { + return change_date(disk, file, new_date, MODIF); } -int ccos_set_exp_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date) { - return change_date(ctx, file, new_date, EXPIR); +int ccos_set_exp_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date) { + return change_date(disk, file, new_date, EXPIR); } -int ccos_get_dir_contents(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries) { +int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries) { uint8_t* dir_contents = NULL; size_t dir_size = 0; - if (ccos_read_file(ctx, dir, data, &dir_contents, &dir_size) == -1) { + if (ccos_read_file(disk, dir, data, &dir_contents, &dir_size) == -1) { fprintf(stderr, "Unable to get directory contents: Unable to read directory!\n"); if (dir_contents != NULL) { free(dir_contents); @@ -113,7 +114,7 @@ int ccos_get_dir_contents(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data, uin parsed_directory_element_t* elements = NULL; // TODO: Do we really need entry count here? *entry_count = dir->desc.dir_count; - int res = parse_directory_data(ctx, data, dir_contents, dir_size, *entry_count, &elements); + int res = parse_directory_data(disk, data, dir_contents, dir_size, *entry_count, &elements); free(dir_contents); if (res == -1) { @@ -160,7 +161,7 @@ int ccos_is_dir(const ccos_inode_t* file) { return strncasecmp(type, CCOS_DIR_TYPE, strlen(CCOS_DIR_TYPE)) == 0; } -int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data) { +int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data) { uint32_t inode_file_size = ccos_get_file_size(file); if (inode_file_size != file_size) { fprintf(stderr, @@ -172,7 +173,7 @@ int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_d size_t block_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(ctx, file, image_data, &block_count, &blocks) != 0) { + if (get_file_blocks(disk, file, image_data, &block_count, &blocks) != 0) { fprintf(stderr, "Unable to write file to image: Unable to get file blocks from the block!\n"); return -1; } @@ -182,7 +183,7 @@ int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_d for (size_t i = 0; i < block_count; ++i) { const uint8_t* start = NULL; size_t data_size = 0; - if (get_block_data(ctx, blocks[i], image_data, &start, &data_size) != 0) { + if (get_block_data(disk, blocks[i], image_data, &start, &data_size) != 0) { fprintf(stderr, "Unable to write data: Unable to get target block address!\n"); free(blocks); return -1; @@ -197,8 +198,8 @@ int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_d return 0; } -char* ccos_get_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size) { - ccos_inode_t* root = ccos_get_root_dir(ctx, data, data_size); +char* ccos_get_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size) { + ccos_inode_t* root = ccos_get_root_dir(disk, data, data_size); char* label = short_string_to_string((short_string_t*)&(root->desc.name_length)); if (strcmp(label, "")) { int sz = strlen(label); @@ -208,19 +209,19 @@ char* ccos_get_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size) { return label; } -int ccos_set_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size, const char* label) { +int ccos_set_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size, const char* label) { char newlab[strlen(label) + 1]; - ccos_inode_t* root = ccos_get_root_dir(ctx, data, data_size); + ccos_inode_t* root = ccos_get_root_dir(disk, data, data_size); if (strcmp(label, "")) { sprintf(newlab, " %s", label); - return ccos_rename_file(ctx, data, data_size, root, newlab, NULL); + return ccos_rename_file(disk, data, data_size, root, newlab, NULL); } else { - return ccos_rename_file(ctx, data, data_size, root, "", NULL); + return ccos_rename_file(disk, data, data_size, root, "", NULL); } } -int ccos_get_image_map(ccfs_handle ctx, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count) { - size_t block_size = get_block_size(ctx); +int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count) { + size_t block_size = get_block_size(disk); size_t block_count = data_size / block_size; if (block_count * block_size != data_size) { fprintf(stderr, "Warn: image size (" SIZE_T " bytes) is not a multiple of a block size (" SIZE_T " bytes)\n", @@ -251,11 +252,11 @@ int ccos_get_image_map(ccfs_handle ctx, const uint8_t* data, size_t data_size, b return 0; } -int ccos_read_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size) { +int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size) { size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(ctx, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for file at 0x%x!\n", file->header.file_id); return -1; } @@ -283,7 +284,7 @@ int ccos_read_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* image_dat for (int i = 0; i < blocks_count; ++i) { const uint8_t* data_start = NULL; size_t data_size = 0; - if (get_block_data(ctx, blocks[i], image_data, &data_start, &data_size) == -1) { + if (get_block_data(disk, blocks[i], image_data, &data_start, &data_size) == -1) { fprintf(stderr, "Unable to get data for data block 0x%x, file at 0x%x\n", blocks[i], file->header.file_id); free(*file_data); return -1; @@ -304,19 +305,19 @@ int ccos_read_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* image_dat return 0; } -int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, size_t image_size, +int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size, const uint8_t* file_data, size_t file_size) { size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(ctx, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for file id 0x%x!\n", file->header.file_id); return -1; } free(blocks); - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(ctx, image_data, image_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, image_size); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to write to file: invalid bitmask!\n"); return -1; @@ -324,7 +325,7 @@ int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, si TRACE("file id 0x%x has %d blocks", file->header.file_id, blocks_count); - size_t log_block_size = get_log_block_size(ctx); + size_t log_block_size = get_log_block_size(disk); // add extra blocks to the file if it's new size is greater than the old size size_t out_blocks_count = (file_size + log_block_size - 1) / log_block_size; if (out_blocks_count != blocks_count) { @@ -335,7 +336,7 @@ int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, si for (int i = 0; i < (out_blocks_count - blocks_count); ++i) { TRACE("Adding %d / %d...", i + 1, (out_blocks_count - blocks_count)); - if (add_block_to_file(ctx, file, image_data, &bitmask_list) == CCOS_INVALID_BLOCK) { + if (add_block_to_file(disk, file, image_data, &bitmask_list) == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to allocate more space for the file 0x%x: no space left!\n", file->header.file_id); return -1; } @@ -346,14 +347,14 @@ int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, si TRACE("Removing %d blocks from the file", blocks_count - out_blocks_count); for (int i = 0; i < (blocks_count - out_blocks_count); ++i) { TRACE("Remove %d / %d...", i + 1, (blocks_count - out_blocks_count)); - if (remove_block_from_file(ctx, file, image_data, &bitmask_list) == -1) { + if (remove_block_from_file(disk, file, image_data, &bitmask_list) == -1) { fprintf(stderr, "Unable to remove block from file at 0x%x!\n", file->header.file_id); return -1; } } } - if (get_file_blocks(ctx, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for the file id 0x%x!\n", file->header.file_id); return -1; } @@ -362,7 +363,7 @@ int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, si for (int i = 0; i < blocks_count; ++i) { uint8_t* start = NULL; size_t data_size = 0; - get_block_data(ctx, blocks[i], image_data, (const uint8_t**)&start, &data_size); + get_block_data(disk, blocks[i], image_data, (const uint8_t**)&start, &data_size); size_t copy_size = MIN(file_size - written, data_size); memcpy(start, &(file_data[written]), copy_size); @@ -381,33 +382,33 @@ int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, si file->desc.dir_length = written; } file->desc.file_size = written; - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); return 0; } // allocate block for the new file inode; copy file inode over; write file contents to the new file; add new file to the // directory -int ccos_copy_file(ccfs_handle ctx, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, +int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, const uint8_t* src_image, ccos_inode_t* src_file) { - ccos_bitmask_list_t dest_bitmask_list = find_bitmask_blocks(ctx, dest_image, dest_image_size); + ccos_bitmask_list_t dest_bitmask_list = find_bitmask_blocks(disk, dest_image, dest_image_size); if (dest_bitmask_list.length == 0) { fprintf(stderr, "Unable to copy file: Unable to get bitmask in destination image!\n"); return -1; } uint16_t free_block = CCOS_INVALID_BLOCK; - if ((free_block = get_free_block(ctx, &dest_bitmask_list)) == CCOS_INVALID_BLOCK) { + if ((free_block = get_free_block(disk, &dest_bitmask_list)) == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to copy file: no space left!\n"); return -1; } - mark_block(ctx, &dest_bitmask_list, free_block, 1); - ccos_inode_t* new_file = init_inode(ctx, free_block, dest_directory->header.file_id, dest_image); + mark_block(disk, &dest_bitmask_list, free_block, 1); + ccos_inode_t* new_file = init_inode(disk, free_block, dest_directory->header.file_id, dest_image); uint8_t* file_data = NULL; size_t file_size = 0; TRACE("Reading file 0x%lx (%*s)", src_file->header.file_id, src_file->desc.name_length, src_file->desc.name); - if (ccos_read_file(ctx, src_file, src_image, &file_data, &file_size) == -1) { + if (ccos_read_file(disk, src_file, src_image, &file_data, &file_size) == -1) { fprintf(stderr, "Unable to read source file with id 0x%x!\n", src_file->header.file_id); return -1; } @@ -417,13 +418,13 @@ int ccos_copy_file(ccfs_handle ctx, uint8_t* dest_image, size_t dest_image_size, offsetof(ccos_inode_t, content_inode_info) - (offsetof(ccos_inode_t, desc) + offsetof(ccos_inode_desc_t, file_size))); TRACE("Writing file 0x%lx", new_file->header.file_id); - if (ccos_write_file(ctx, new_file, dest_image, dest_image_size, file_data, file_size) == -1) { + if (ccos_write_file(disk, new_file, dest_image, dest_image_size, file_data, file_size) == -1) { fprintf(stderr, "Unable to write file to file with id 0x%x!\n", free_block); free(file_data); return -1; } - int res = add_file_to_directory(ctx, dest_directory, new_file, dest_image, dest_image_size); + int res = add_file_to_directory(disk, dest_directory, new_file, dest_image, dest_image_size); free(file_data); if (res == -1) { @@ -441,72 +442,72 @@ int ccos_copy_file(ccfs_handle ctx, uint8_t* dest_image, size_t dest_image_size, // - Update directory checksums // - Find all file blocks; clear them and mark as free // - Clear all file content inode blocks and mark as free -int ccos_delete_file(ccfs_handle ctx, uint8_t* image_data, size_t data_size, ccos_inode_t* file) { +int ccos_delete_file(ccos_disk_t* disk, uint8_t* image_data, size_t data_size, ccos_inode_t* file) { if (ccos_is_dir(file)) { TRACE("Recursively deleting files in the directory %*s (0x%x)", file->desc.name_length, file->desc.name, file->header.file_id); uint16_t files = 0; ccos_inode_t** content = NULL; - ccos_get_dir_contents(ctx, file, image_data, &files, &content); + ccos_get_dir_contents(disk, file, image_data, &files, &content); for (int c = 0; c < files; c++) { - ccos_delete_file(ctx, image_data, data_size, content[c]); + ccos_delete_file(disk, image_data, data_size, content[c]); } free(content); } - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(ctx, image_data, data_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, data_size); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to delete file: Unable to find image bitmask!\n"); return -1; } - if (delete_file_from_parent_dir(ctx, file, image_data, data_size) == -1){ + if (delete_file_from_parent_dir(disk, file, image_data, data_size) == -1){ fprintf(stderr, "Unable to delete file: Unable to delete file entry from parent dir!\n"); return -1; } size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(ctx, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to read file blocks of file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); return -1; } for (int j = 0; j < blocks_count; ++j) { - erase_block(ctx, blocks[j], image_data, &bitmask_list); + erase_block(disk, blocks[j], image_data, &bitmask_list); } free(blocks); while (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - if (remove_content_inode(ctx, file, image_data, &bitmask_list) == -1) { + if (remove_content_inode(disk, file, image_data, &bitmask_list) == -1) { fprintf(stderr, "Unable to remove content block from the file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); return -1; } } - erase_block(ctx, file->header.file_id, image_data, &bitmask_list); + erase_block(disk, file->header.file_id, image_data, &bitmask_list); return 0; } -ccos_inode_t* ccos_add_file(ccfs_handle ctx, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, +ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, uint8_t* image_data, size_t image_size) { - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(ctx, image_data, image_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, image_size); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to add file: Unable to find bitmask in the image!\n"); return NULL; } uint16_t free_block = CCOS_INVALID_BLOCK; - if ((free_block = get_free_block(ctx, &bitmask_list)) == CCOS_INVALID_BLOCK) { + if ((free_block = get_free_block(disk, &bitmask_list)) == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to get free block: No space left!\n"); return NULL; } - mark_block(ctx, &bitmask_list, free_block, 1); - ccos_inode_t* new_file = init_inode(ctx, free_block, dest_directory->header.file_id, image_data); + mark_block(disk, &bitmask_list, free_block, 1); + ccos_inode_t* new_file = init_inode(disk, free_block, dest_directory->header.file_id, image_data); TRACE("Filling file info..."); new_file->desc.file_size = file_size; @@ -532,12 +533,12 @@ ccos_inode_t* ccos_add_file(ccfs_handle ctx, ccos_inode_t* dest_directory, uint8 new_file->desc.expiration_date = (ccos_date_t){}; TRACE("Writing file 0x%lx", new_file->header.file_id); - if (ccos_write_file(ctx, new_file, image_data, image_size, file_data, file_size) == -1) { + if (ccos_write_file(disk, new_file, image_data, image_size, file_data, file_size) == -1) { fprintf(stderr, "Unable to write file to file with id 0x%x!\n", new_file->header.file_id); return NULL; } - int res = add_file_to_directory(ctx, dest_directory, new_file, image_data, image_size); + int res = add_file_to_directory(disk, dest_directory, new_file, image_data, image_size); if (res == -1) { fprintf(stderr, "Unable to copy file: unable to add new file with id 0x%x to the directory with id 0x%x!\n", @@ -548,18 +549,18 @@ ccos_inode_t* ccos_add_file(ccfs_handle ctx, ccos_inode_t* dest_directory, uint8 return new_file; } -ccos_inode_t* ccos_get_root_dir(ccfs_handle ctx, uint8_t* data, size_t data_size) { +ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk, uint8_t* data, size_t data_size) { uint16_t superblock = 0; - if (get_superblock(ctx, data, data_size, &superblock) == -1) { + if (get_superblock(disk, data, data_size, &superblock) == -1) { fprintf(stderr, "Unable to get root directory: unable to get superblock!\n"); return NULL; } - return get_inode(ctx, superblock, data); + return get_inode(disk, superblock, data); } -int ccos_validate_file(ccfs_handle ctx, const ccos_inode_t* file) { +int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file) { uint16_t metadata_checksum = calc_inode_metadata_checksum(file); if (metadata_checksum != file->desc.metadata_checksum) { fprintf(stderr, "Warn: Invalid metadata checksum: expected 0x%hx, got 0x%hx\n", @@ -567,7 +568,7 @@ int ccos_validate_file(ccfs_handle ctx, const ccos_inode_t* file) { return -1; } - uint16_t blocks_checksum = calc_inode_blocks_checksum(ctx, file); + uint16_t blocks_checksum = calc_inode_blocks_checksum(disk, file); if (blocks_checksum != file->content_inode_info.blocks_checksum) { fprintf(stderr, "Warn: Invalid block data checksum: expected 0x%hx, got 0x%hx!\n", file->content_inode_info.blocks_checksum, blocks_checksum); @@ -583,9 +584,9 @@ int ccos_validate_file(ccfs_handle ctx, const ccos_inode_t* file) { return 0; } -size_t ccos_calc_free_space(ccfs_handle ctx, uint8_t* data, size_t data_size) { +size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size) { uint16_t superblock = 0; - if (get_superblock(ctx, data, data_size, &superblock) == -1) { + if (get_superblock(disk, data, data_size, &superblock) == -1) { fprintf(stderr, "Unable to calculate free space: Unable to get superblock!\n"); return -1; } @@ -593,13 +594,13 @@ size_t ccos_calc_free_space(ccfs_handle ctx, uint8_t* data, size_t data_size) { uint16_t* free_blocks = NULL; size_t free_blocks_count = 0; - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(ctx, data, data_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, data, data_size); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to calculate free space on the image: Unable to find bitmask!\n"); return -1; } - if (get_free_blocks(ctx, &bitmask_list, data_size, &free_blocks_count, &free_blocks) == -1) { + if (get_free_blocks(disk, &bitmask_list, data_size, &free_blocks_count, &free_blocks) == -1) { fprintf(stderr, "Unable to calculate free space: Unable to get free blocks!\n"); if (free_blocks != NULL) { free(free_blocks); @@ -609,19 +610,19 @@ size_t ccos_calc_free_space(ccfs_handle ctx, uint8_t* data, size_t data_size) { } free(free_blocks); - return free_blocks_count * get_block_size(ctx); + return free_blocks_count * get_block_size(disk); } -ccos_inode_t* ccos_get_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data) { +ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data) { uint16_t parent_dir_id = file->desc.dir_file_id; - return get_inode(ctx, parent_dir_id, data); + return get_inode(disk, parent_dir_id, data); } int ccos_parse_file_name(const ccos_inode_t* inode, char* basename, char* type, size_t* name_length, size_t* type_length) { return parse_file_name((const short_string_t*)&(inode->desc.name_length), basename, type, name_length, type_length); } -ccos_inode_t* ccos_create_dir(ccfs_handle ctx, ccos_inode_t* parent_dir, const char* directory_name, +ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name, uint8_t* image_data, size_t image_size) { const char* dir_suffix = "~subject~"; @@ -634,7 +635,7 @@ ccos_inode_t* ccos_create_dir(ccfs_handle ctx, ccos_inode_t* parent_dir, const c sprintf(filename, "%s%s", directory_name, dir_suffix); uint8_t directory_contents = CCOS_DIR_LAST_ENTRY_MARKER; - ccos_inode_t* new_directory = ccos_add_file(ctx, parent_dir, &directory_contents, get_dir_default_size(ctx), filename, image_data, image_size); + ccos_inode_t* new_directory = ccos_add_file(disk, parent_dir, &directory_contents, get_dir_default_size(disk), filename, image_data, image_size); free(filename); if (new_directory == NULL) { @@ -650,11 +651,11 @@ ccos_inode_t* ccos_create_dir(ccfs_handle ctx, ccos_inode_t* parent_dir, const c new_directory->desc.pswd[2] = '\x47'; new_directory->desc.pswd[3] = '\xC7'; - update_inode_checksums(ctx, new_directory); + update_inode_checksums(disk, new_directory); return new_directory; } -int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, ccos_inode_t* file, +int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, ccos_inode_t* file, const char* new_name, const char* new_type) { char name[CCOS_MAX_FILE_NAME] = {0}; char type[CCOS_MAX_FILE_NAME] = {0}; @@ -665,9 +666,9 @@ int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, cc return -1; } - ccos_inode_t* parent_dir = ccos_get_parent_dir(ctx, file, image_data); + ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file, image_data); - if (delete_file_from_parent_dir(ctx, file, image_data, image_size) == -1){ + if (delete_file_from_parent_dir(disk, file, image_data, image_size) == -1){ fprintf(stderr, "Unable to rename file: Unable to delete old file entry from parent dir!\n"); return -1; } @@ -682,7 +683,7 @@ int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, cc file->desc.name_length = strlen(file->desc.name); - if (add_file_to_directory(ctx, parent_dir, file, image_data, image_size) == -1){ + if (add_file_to_directory(disk, parent_dir, file, image_data, image_size) == -1){ fprintf(stderr, "Unable to rename file: Unable to add new file entry from parent dir!\n"); return -1; } @@ -690,7 +691,7 @@ int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, cc memset(file->desc.name, 0, CCOS_MAX_FILE_NAME); snprintf(file->desc.name, CCOS_MAX_FILE_NAME, "%s", new_name); file->desc.name_length = strlen(file->desc.name); - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); } return 0; diff --git a/ccos_image.h b/ccos_image.h index a79abb3..64a6410 100644 --- a/ccos_image.h +++ b/ccos_image.h @@ -2,7 +2,6 @@ #define CCOS_IMAGE_H #include "ccos_structure.h" -#include "ccos_format.h" #include "string_utils.h" typedef struct { @@ -51,7 +50,7 @@ version_t ccos_get_file_version(const ccos_inode_t* file); * * @return 0 on success, -1 otherwise. */ -int ccos_set_file_version(ccfs_handle ctx, ccos_inode_t* file, version_t new_version); +int ccos_set_file_version(ccos_disk_t* disk, ccos_inode_t* file, version_t new_version); /** * @brief Get the name of the file. @@ -71,7 +70,7 @@ short_string_t* ccos_get_file_name(const ccos_inode_t* file); * * @return Root directory on success, NULL otherwise. */ -ccos_inode_t* ccos_get_root_dir(ccfs_handle ctx, uint8_t* data, size_t data_size); +ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk, uint8_t* data, size_t data_size); /** * @brief Read contents from the directory inode. @@ -84,7 +83,7 @@ ccos_inode_t* ccos_get_root_dir(ccfs_handle ctx, uint8_t* data, size_t data_size * * @return 0 on success, -1 otherwise. */ -int ccos_get_dir_contents(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries); +int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries); /** * @brief Determine whether the given inode is a directory's inode. @@ -140,7 +139,7 @@ ccos_date_t ccos_get_exp_date(const ccos_inode_t* file); * * @return 0 on success, -1 otherwise. */ -int ccos_set_creation_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date); +int ccos_set_creation_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date); /** * @brief Changes the modification date of a file or folder. @@ -151,7 +150,7 @@ int ccos_set_creation_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_ * * @return 0 on success, -1 otherwise. */ -int ccos_set_mod_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date); +int ccos_set_mod_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date); /** * @brief Changes the expiration date of a file or folder. @@ -162,7 +161,7 @@ int ccos_set_mod_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date) * * @return 0 on success, -1 otherwise. */ -int ccos_set_exp_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date); +int ccos_set_exp_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date); /** * @brief Replace file in the CCOS image data. @@ -175,7 +174,7 @@ int ccos_set_exp_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date) * * @return 0 on success, -1 otherwise. */ -int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data); +int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data); /** * @brief Get info about blocks in the image. Traverse all blocks in the CCOS image and return array filled with @@ -189,7 +188,7 @@ int ccos_replace_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* file_d * * @return 0 on success, -1 otherwise. */ -int ccos_get_image_map(ccfs_handle ctx, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count); +int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count); /** * @brief Read file contents into memory buffer. @@ -202,7 +201,7 @@ int ccos_get_image_map(ccfs_handle ctx, const uint8_t* data, size_t data_size, b * * @return 0 on success, -1 otherwise. */ -int ccos_read_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size); +int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size); /** * @brief Get parent directory of the given file. @@ -213,7 +212,7 @@ int ccos_read_file(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* image_dat * * @return Parent directory on success, NULL otherwise. */ -ccos_inode_t* ccos_get_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data); +ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data); /** * @brief Copy file from one CCOS image into another. @@ -227,7 +226,7 @@ ccos_inode_t* ccos_get_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* * * @return 0 on success, -1 otherwise. */ -int ccos_copy_file(ccfs_handle ctx, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, +int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, const uint8_t* src_image, ccos_inode_t* src_file); /** @@ -240,7 +239,7 @@ int ccos_copy_file(ccfs_handle ctx, uint8_t* dest_image, size_t dest_image_size, * * @return 0 on success, -1 otherwise. */ -int ccos_delete_file(ccfs_handle ctx, uint8_t* image_data, size_t data_size, ccos_inode_t* file); +int ccos_delete_file(ccos_disk_t* disk, uint8_t* image_data, size_t data_size, ccos_inode_t* file); /** * @brief Add new file to the given directory. @@ -255,7 +254,7 @@ int ccos_delete_file(ccfs_handle ctx, uint8_t* image_data, size_t data_size, cco * * @return Newly created file inode on success, NULL otherwise. */ -ccos_inode_t* ccos_add_file(ccfs_handle ctx, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, +ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, uint8_t* image_data, size_t image_size); /** @@ -266,7 +265,7 @@ ccos_inode_t* ccos_add_file(ccfs_handle ctx, ccos_inode_t* dest_directory, uint8 * * @return 0 on success, -1 otherwise. */ -int ccos_validate_file(ccfs_handle ctx, const ccos_inode_t* file); +int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file); /** * @brief Return amount of free space available in the image. @@ -277,7 +276,7 @@ int ccos_validate_file(ccfs_handle ctx, const ccos_inode_t* file); * * @return Free space in the image, in bytes. */ -size_t ccos_calc_free_space(ccfs_handle ctx, uint8_t* data, size_t data_size); +size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size); /** * @brief Overwrite file contents with the given data. @@ -291,7 +290,7 @@ size_t ccos_calc_free_space(ccfs_handle ctx, uint8_t* data, size_t data_size); * * @return 0 on success, -1 otherwise. */ -int ccos_write_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, size_t image_size, +int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size, const uint8_t* file_data, size_t file_size); /** @@ -318,7 +317,7 @@ int ccos_parse_file_name(const ccos_inode_t* inode, char* basename, char* type, * * @return Newly created directory inode on success, NULL otherwise. */ -ccos_inode_t* ccos_create_dir(ccfs_handle ctx, ccos_inode_t* parent_dir, const char* directory_name, +ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name, uint8_t* image_data, size_t image_size); /** @@ -333,7 +332,7 @@ ccos_inode_t* ccos_create_dir(ccfs_handle ctx, ccos_inode_t* parent_dir, const c * * @return 0 on success, -1 otherwise. */ -int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, ccos_inode_t* file, +int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, ccos_inode_t* file, const char* new_name, const char* new_type); /** @@ -345,7 +344,7 @@ int ccos_rename_file(ccfs_handle ctx, uint8_t* image_data, size_t image_size, cc * * @return Image label in char* */ -char* ccos_get_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size); +char* ccos_get_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size); /** * @brief Set label of provided image. @@ -357,6 +356,6 @@ char* ccos_get_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size); * * @return 0 on success, -1 otherwise. */ -int ccos_set_image_label(ccfs_handle ctx, uint8_t* data, size_t data_size, const char* label); +int ccos_set_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size, const char* label); #endif // CCOS_IMAGE_H diff --git a/ccos_private.c b/ccos_private.c index 3060ba8..a0b047d 100644 --- a/ccos_private.c +++ b/ccos_private.c @@ -32,9 +32,9 @@ uint16_t calc_inode_metadata_checksum(const ccos_inode_t* inode) { return calc_checksum((const uint8_t*)inode, offsetof(ccos_inode_t, desc) + offsetof(ccos_inode_desc_t, metadata_checksum)); } -uint16_t calc_inode_blocks_checksum(ccfs_handle ctx, const ccos_inode_t* inode) { +uint16_t calc_inode_blocks_checksum(ccos_disk_t* disk, const ccos_inode_t* inode) { const uint8_t* checksum_data = (const uint8_t*)&inode->content_inode_info.block_next; - uint16_t checksum_data_size = get_log_block_size(ctx) + uint16_t checksum_data_size = get_log_block_size(disk) - sizeof(ccos_inode_desc_t) - offsetof(ccos_block_data_t, block_next); @@ -45,11 +45,11 @@ uint16_t calc_inode_blocks_checksum(ccfs_handle ctx, const ccos_inode_t* inode) return blocks_checksum; } -uint16_t calc_content_inode_checksum(ccfs_handle ctx, const ccos_content_inode_t* content_inode) { +uint16_t calc_content_inode_checksum(ccos_disk_t* disk, const ccos_content_inode_t* content_inode) { const size_t start_offset = offsetof(ccos_content_inode_t, content_inode_info) + offsetof(ccos_block_data_t, block_next); const uint8_t *checksum_data = (const uint8_t*)&content_inode->content_inode_info.block_next; - uint16_t checksum_data_size = get_block_size(ctx) - start_offset - get_content_inode_padding(ctx); + uint16_t checksum_data_size = get_block_size(disk) - start_offset - get_content_inode_padding(disk); uint16_t blocks_checksum = calc_checksum(checksum_data, checksum_data_size); blocks_checksum += content_inode->content_inode_info.header.file_id; @@ -58,9 +58,9 @@ uint16_t calc_content_inode_checksum(ccfs_handle ctx, const ccos_content_inode_t return blocks_checksum; } -uint16_t calc_bitmask_checksum(ccfs_handle ctx, const ccos_bitmask_t* bitmask) { +uint16_t calc_bitmask_checksum(ccos_disk_t* disk, const ccos_bitmask_t* bitmask) { const uint8_t* checksum_data = (const uint8_t*)&bitmask->allocated; - uint16_t checksum_data_size = get_bitmask_size(ctx) + sizeof(bitmask->allocated); + uint16_t checksum_data_size = get_bitmask_size(disk) + sizeof(bitmask->allocated); uint16_t checksum = calc_checksum(checksum_data, checksum_data_size); checksum += bitmask->header.file_id; @@ -69,36 +69,36 @@ uint16_t calc_bitmask_checksum(ccfs_handle ctx, const ccos_bitmask_t* bitmask) { return checksum; } -void update_inode_checksums(ccfs_handle ctx, ccos_inode_t* inode) { +void update_inode_checksums(ccos_disk_t* disk, ccos_inode_t* inode) { inode->desc.metadata_checksum = calc_inode_metadata_checksum(inode); - inode->content_inode_info.blocks_checksum = calc_inode_blocks_checksum(ctx, inode); + inode->content_inode_info.blocks_checksum = calc_inode_blocks_checksum(disk, inode); } -void update_content_inode_checksums(ccfs_handle ctx, ccos_content_inode_t* content_inode) { - content_inode->content_inode_info.blocks_checksum = calc_content_inode_checksum(ctx, content_inode); +void update_content_inode_checksums(ccos_disk_t* disk, ccos_content_inode_t* content_inode) { + content_inode->content_inode_info.blocks_checksum = calc_content_inode_checksum(disk, content_inode); } -void update_bitmask_checksum(ccfs_handle ctx, ccos_bitmask_t* bitmask) { - bitmask->checksum = calc_bitmask_checksum(ctx, bitmask); +void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask) { + bitmask->checksum = calc_bitmask_checksum(disk, bitmask); } -ccos_inode_t* get_inode(ccfs_handle ctx, uint16_t block, const uint8_t* data) { - size_t block_size = get_block_size(ctx); +ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data) { + size_t block_size = get_block_size(disk); uint32_t addr = block * block_size; return (ccos_inode_t*)&(data[addr]); } -ccos_content_inode_t* get_content_inode(ccfs_handle ctx, uint16_t block, const uint8_t* data) { - size_t block_size = get_block_size(ctx); +ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data) { + size_t block_size = get_block_size(disk); uint32_t addr = block * block_size; return (ccos_content_inode_t*)&(data[addr]); } -int get_superblock(ccfs_handle ctx, const uint8_t* data, size_t image_size, uint16_t* superblock) { +int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, uint16_t* superblock) { uint16_t sb = *(uint16_t*)&data[CCOS_SUPERBLOCK_ADDR_OFFSET]; - if (sb == 0) sb = ctx->superblock_id; + if (sb == 0) sb = disk->superblock_fid; - size_t block_size = get_block_size(ctx); + size_t block_size = get_block_size(disk); uint32_t blocks_in_image = image_size / block_size; if (sb > blocks_in_image) { @@ -119,9 +119,9 @@ int get_superblock(ccfs_handle ctx, const uint8_t* data, size_t image_size, uint return 0; } -int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks) { - size_t inode_max_blocks = get_inode_max_blocks(ctx); - size_t content_inode_max_blocks = get_content_inode_max_blocks(ctx); +int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks) { + size_t inode_max_blocks = get_inode_max_blocks(disk); + size_t content_inode_max_blocks = get_content_inode_max_blocks(disk); *blocks = calloc(inode_max_blocks, sizeof(uint16_t)); if (*blocks == NULL) { @@ -145,11 +145,11 @@ int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, si if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { TRACE("Has more than 1 block!"); - ccos_content_inode_t* content_inode = get_content_inode(ctx, file->content_inode_info.block_next, data); + ccos_content_inode_t* content_inode = get_content_inode(disk, file->content_inode_info.block_next, data); for (;;) { TRACE("Processing extra block 0x%lx...", file->content_inode_info.block_next); - uint16_t checksum = calc_content_inode_checksum(ctx, content_inode); + uint16_t checksum = calc_content_inode_checksum(disk, content_inode); if (checksum != content_inode->content_inode_info.blocks_checksum) { fprintf(stderr, "Warn: Blocks checksum mismatch: expected 0x%04hx, got 0x%04hx\n", @@ -193,7 +193,7 @@ int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, si break; } - content_inode = get_content_inode(ctx, content_inode->content_inode_info.block_next, data); + content_inode = get_content_inode(disk, content_inode->content_inode_info.block_next, data); } } @@ -201,12 +201,12 @@ int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, si return 0; } -static ccos_bitmask_t* get_bitmask(ccfs_handle ctx, uint8_t* data, size_t data_size) { - size_t block_size = get_block_size(ctx); +static ccos_bitmask_t* get_bitmask(ccos_disk_t* disk, uint8_t* data, size_t data_size) { + size_t block_size = get_block_size(disk); uint16_t bitmask_block = *((uint16_t*)&(data[CCOS_BITMASK_ADDR_OFFSET])); - // FIXME: always use values from ctx->bitmap_block_id. - if (bitmask_block == 0 || bitmask_block == 0x5555) bitmask_block = ctx->bitmap_block_id; + // FIXME: always use values from disk->bitmap_block_id. + if (bitmask_block == 0 || bitmask_block == 0x5555) bitmask_block = disk->bitmap_fid; uint32_t blocks_in_image = data_size / block_size; if (bitmask_block > blocks_in_image) { @@ -227,15 +227,15 @@ static ccos_bitmask_t* get_bitmask(ccfs_handle ctx, uint8_t* data, size_t data_s return (ccos_bitmask_t*)&(data[address]); } -ccos_bitmask_list_t find_bitmask_blocks(ccfs_handle ctx, uint8_t* data, size_t data_size) { +ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk, uint8_t* data, size_t data_size) { ccos_bitmask_list_t result = {0}; - ccos_bitmask_t* first_bitmask_block = get_bitmask(ctx, data, data_size); + ccos_bitmask_t* first_bitmask_block = get_bitmask(disk, data, data_size); if (first_bitmask_block == NULL) { fprintf(stderr, "Unable to get bitmask blocks: No bitmask in image!\n"); return result; } - size_t block_size = get_block_size(ctx); + size_t block_size = get_block_size(disk); uint16_t bitmask_id = first_bitmask_block->header.file_id; uint32_t bitmask_addr = bitmask_id * block_size; @@ -261,8 +261,8 @@ ccos_bitmask_list_t find_bitmask_blocks(ccfs_handle ctx, uint8_t* data, size_t d } // TODO: move to the separate file -uint16_t get_free_block(ccfs_handle ctx, const ccos_bitmask_list_t* bitmask_list) { - size_t bitmask_size = get_bitmask_size(ctx); +uint16_t get_free_block(ccos_disk_t* disk, const ccos_bitmask_list_t* bitmask_list) { + size_t bitmask_size = get_bitmask_size(disk); for (size_t block = 0; block < bitmask_list->length; block++) { for (int i = 0; i < bitmask_size; ++i) { uint8_t* bitmask_bytes = get_bitmask_bytes(bitmask_list->bitmask_blocks[block]); @@ -282,10 +282,10 @@ uint16_t get_free_block(ccfs_handle ctx, const ccos_bitmask_list_t* bitmask_list return CCOS_INVALID_BLOCK; } -void mark_block(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, uint16_t block, uint8_t mode) { +void mark_block(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, uint16_t block, uint8_t mode) { TRACE("Mark block %x as %s...", block, mode ? "used" : "free"); - size_t bitmask_blocks = get_bitmask_blocks(ctx); + size_t bitmask_blocks = get_bitmask_blocks(disk); if (block >= bitmask_list->length * bitmask_blocks) { fprintf(stderr, "Unable to mark block 0x%x: out of bitmask bounds of %lx!\n", block, @@ -311,13 +311,13 @@ void mark_block(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, uint16_t blo bitmask_list->bitmask_blocks[i]->allocated -= 1; } - update_bitmask_checksum(ctx, bitmask_list->bitmask_blocks[i]); + update_bitmask_checksum(disk, bitmask_list->bitmask_blocks[i]); } } -ccos_inode_t* init_inode(ccfs_handle ctx, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data) { +ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data) { TRACE("Initializing inode at 0x%x!", block); - ccos_inode_t* inode = get_inode(ctx, block, image_data); + ccos_inode_t* inode = get_inode(disk, block, image_data); memset(inode, 0, sizeof(ccos_inode_t)); inode->header.file_id = block; inode->desc.dir_file_id = parent_dir_block; @@ -326,33 +326,33 @@ ccos_inode_t* init_inode(ccfs_handle ctx, uint16_t block, uint16_t parent_dir_bl inode->content_inode_info.block_current = block; inode->content_inode_info.block_prev = CCOS_INVALID_BLOCK; - size_t inode_max_blocks = get_inode_max_blocks(ctx); + size_t inode_max_blocks = get_inode_max_blocks(disk); uint16_t* content_blocks = get_inode_content_blocks(inode); for (int i = 0; i < inode_max_blocks; ++i) { content_blocks[i] = CCOS_CONTENT_BLOCKS_END_MARKER; } - update_inode_checksums(ctx, inode); + update_inode_checksums(disk, inode); return inode; } -ccos_content_inode_t* add_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { ccos_block_data_t* content_inode_info = &(file->content_inode_info); - ccos_content_inode_t* last_content_inode = get_last_content_inode(ctx, file, data); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); if (last_content_inode != NULL) { content_inode_info = &(last_content_inode->content_inode_info); } - uint16_t new_block = get_free_block(ctx, bitmask_list); + uint16_t new_block = get_free_block(disk, bitmask_list); if (new_block == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to allocate new content inode: No free space!\n"); return NULL; } - mark_block(ctx, bitmask_list, new_block, 1); + mark_block(disk, bitmask_list, new_block, 1); - ccos_content_inode_t* content_inode = get_content_inode(ctx, new_block, data); + ccos_content_inode_t* content_inode = get_content_inode(disk, new_block, data); content_inode->content_inode_info.header.file_id = content_inode_info->header.file_id; content_inode->content_inode_info.header.file_fragment_index = content_inode_info->header.file_fragment_index; @@ -362,21 +362,21 @@ ccos_content_inode_t* add_content_inode(ccfs_handle ctx, ccos_inode_t* file, uin content_inode_info->block_next = new_block; - update_content_inode_checksums(ctx, content_inode); + update_content_inode_checksums(disk, content_inode); if (last_content_inode != NULL) { - update_content_inode_checksums(ctx, last_content_inode); + update_content_inode_checksums(disk, last_content_inode); } else { - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); } return content_inode; } -ccos_content_inode_t* get_last_content_inode(ccfs_handle ctx, const ccos_inode_t* file, const uint8_t* image_data) { +ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file, const uint8_t* image_data) { if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - ccos_content_inode_t* result = get_content_inode(ctx, file->content_inode_info.block_next, image_data); + ccos_content_inode_t* result = get_content_inode(disk, file->content_inode_info.block_next, image_data); while (result->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - result = get_content_inode(ctx, result->content_inode_info.block_next, image_data); + result = get_content_inode(disk, result->content_inode_info.block_next, image_data); } return result; @@ -385,15 +385,15 @@ ccos_content_inode_t* get_last_content_inode(ccfs_handle ctx, const ccos_inode_t return NULL; } -void erase_block(ccfs_handle ctx, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list) { - size_t block_size = get_block_size(ctx); +void erase_block(ccos_disk_t* disk, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list) { + size_t block_size = get_block_size(disk); uint32_t address = block * block_size; memset(&image[address], 0, block_size); *(uint32_t*)&(image[address]) = CCOS_EMPTY_BLOCK_MARKER; - mark_block(ctx, bitmask_list, block, 0); + mark_block(disk, bitmask_list, block, 0); } -int remove_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { if (file->content_inode_info.block_next == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to remove content inode: no content inodes found in file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); @@ -402,28 +402,28 @@ int remove_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, cco ccos_content_inode_t* prev_inode = NULL; ccos_block_data_t* prev_block_data = &(file->content_inode_info); - ccos_content_inode_t* last_content_inode = get_last_content_inode(ctx, file, data); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); - erase_block(ctx, last_content_inode->content_inode_info.block_current, data, bitmask_list); + erase_block(disk, last_content_inode->content_inode_info.block_current, data, bitmask_list); prev_block_data->block_next = CCOS_INVALID_BLOCK; if (prev_inode != NULL) { - update_content_inode_checksums(ctx, prev_inode); + update_content_inode_checksums(disk, prev_inode); } else { - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); } return 0; } // remove last content block from the file -int remove_block_from_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { uint16_t* content_blocks = get_inode_content_blocks(file); - ccos_content_inode_t* last_content_inode = get_last_content_inode(ctx, file, data); - int content_blocks_count = get_inode_max_blocks(ctx); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); + int content_blocks_count = get_inode_max_blocks(disk); if (last_content_inode != NULL) { content_blocks = get_content_inode_content_blocks(last_content_inode); - content_blocks_count = get_content_inode_max_blocks(ctx); + content_blocks_count = get_content_inode_max_blocks(disk); } uint16_t last_content_block = CCOS_INVALID_BLOCK; @@ -445,41 +445,41 @@ int remove_block_from_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c } if (last_content_block != CCOS_INVALID_BLOCK) { - erase_block(ctx, last_content_block, data, bitmask_list); + erase_block(disk, last_content_block, data, bitmask_list); *(uint16_t*)&(content_blocks[last_content_block_index - 1]) = CCOS_INVALID_BLOCK; } if (last_content_block_index <= 1) { - if (remove_content_inode(ctx, file, data, bitmask_list) == -1) { + if (remove_content_inode(disk, file, data, bitmask_list) == -1) { fprintf(stderr, "Unable to remove content inode after freeing block at file 0x%x!\n", file->header.file_id); return -1; } } if (last_content_inode != NULL) { - update_content_inode_checksums(ctx, last_content_inode); + update_content_inode_checksums(disk, last_content_inode); } else { - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); } return 0; } // get new block from empty blocks, modify it's header properly, reference it in the inode -uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { ccos_content_inode_t* last_content_inode = NULL; - size_t block_size = get_block_size(ctx); + size_t block_size = get_block_size(disk); uint16_t* content_blocks = get_inode_content_blocks(file); - size_t max_content_blocks = get_inode_max_blocks(ctx); + size_t max_content_blocks = get_inode_max_blocks(disk); int content_blocks_count = max_content_blocks; if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { TRACE("Has content inode!"); - last_content_inode = get_last_content_inode(ctx, file, data); + last_content_inode = get_last_content_inode(disk, file, data); content_blocks = get_content_inode_content_blocks(last_content_inode); - content_blocks_count = get_content_inode_max_blocks(ctx); + content_blocks_count = get_content_inode_max_blocks(disk); } uint16_t last_content_block = 0; @@ -502,14 +502,14 @@ uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c last_content_block = content_blocks[last_content_block_index - 1]; } - uint16_t new_block = get_free_block(ctx, bitmask_list); + uint16_t new_block = get_free_block(disk, bitmask_list); if (new_block == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to allocate new content block: No free space!\n"); return CCOS_INVALID_BLOCK; } TRACE("Allocating content block 0x%x for file id 0x%x.", new_block, file->header.file_id); - mark_block(ctx, bitmask_list, new_block, 1); + mark_block(disk, bitmask_list, new_block, 1); TRACE("Last content block is 0x%x", last_content_block); uint32_t new_block_address = new_block * block_size; @@ -532,7 +532,7 @@ uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c TRACE("Allocating new content inode for 0x%x...", file->header.file_id); // we're run out of space for content blocks; we should allocate next content inode - ccos_content_inode_t* new_content_inode = add_content_inode(ctx, file, data, bitmask_list); + ccos_content_inode_t* new_content_inode = add_content_inode(disk, file, data, bitmask_list); if (new_content_inode == NULL) { fprintf(stderr, "Unable to append new content inode to the file: no free space!\n"); return CCOS_INVALID_BLOCK; @@ -540,7 +540,7 @@ uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c last_content_inode = new_content_inode; content_blocks = get_content_inode_content_blocks(new_content_inode); - content_blocks_count = get_content_inode_max_blocks(ctx); + content_blocks_count = get_content_inode_max_blocks(disk); last_content_block_index = 0; } @@ -551,16 +551,16 @@ uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c content_blocks[last_content_block_index + 1] = CCOS_INVALID_BLOCK; } - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); if (last_content_inode != NULL) { - update_content_inode_checksums(ctx, last_content_inode); + update_content_inode_checksums(disk, last_content_inode); } return new_block; } -int add_file_to_directory(ccfs_handle ctx, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { - if (add_file_entry_to_dir_contents(ctx, directory, image_data, image_size, file) == -1) { +int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { + if (add_file_entry_to_dir_contents(disk, directory, image_data, image_size, file) == -1) { fprintf(stderr, "Unable to add file with id 0x%x to directory with id 0x%x!\n", file->header.file_id, directory->header.file_id); return -1; @@ -569,13 +569,13 @@ int add_file_to_directory(ccfs_handle ctx, ccos_inode_t* directory, ccos_inode_t file->desc.dir_file_id = directory->header.file_id; directory->desc.dir_count += 1; - update_inode_checksums(ctx, file); - update_inode_checksums(ctx, directory); + update_inode_checksums(disk, file); + update_inode_checksums(disk, directory); return 0; } -int parse_directory_data(ccfs_handle ctx, uint8_t* image_data, +int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, const uint8_t* directory_data, size_t directory_data_size, uint16_t entry_count, parsed_directory_element_t** entries) { *entries = (parsed_directory_element_t*)calloc(entry_count, sizeof(parsed_directory_element_t)); @@ -604,7 +604,7 @@ int parse_directory_data(ccfs_handle ctx, uint8_t* image_data, (*entries)[count].offset = offset; (*entries)[count].size = entry_size; - (*entries)[count].file = get_inode(ctx, entry_block, image_data); + (*entries)[count].file = get_inode(disk, entry_block, image_data); offset += entry_size; } @@ -648,7 +648,7 @@ static int create_directory_entry(ccos_inode_t* file, int is_last, size_t* entry // find a place for the new filename in dir contents (all files are located there in alphabetical, case-insensitive // order), and insert it there -int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, +int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, uint8_t* image_data, size_t image_size, ccos_inode_t* file) { TRACE("Directory size: %d bytes, length: %d, has %d entries", @@ -657,7 +657,7 @@ int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, uint8_t* directory_data = NULL; size_t dir_size = 0; - if (ccos_read_file(ctx, directory, image_data, &directory_data, &dir_size) == -1) { + if (ccos_read_file(disk, directory, image_data, &directory_data, &dir_size) == -1) { fprintf(stderr, "Unable to get directory contents: Unable to read directory!\n"); if (directory_data != NULL) { free(directory_data); @@ -666,7 +666,7 @@ int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, } parsed_directory_element_t* elements = NULL; - if (parse_directory_data(ctx, image_data, directory_data, dir_size, directory->desc.dir_count, &elements) == -1) { + if (parse_directory_data(disk, image_data, directory_data, dir_size, directory->desc.dir_count, &elements) == -1) { fprintf(stderr, "Unable to add file to directory files list: Unable to parse directory data!\n"); return -1; } @@ -749,7 +749,7 @@ int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, } // 5. Save changes - int res = ccos_write_file(ctx, directory, image_data, image_size, directory_data, new_dir_size); + int res = ccos_write_file(disk, directory, image_data, image_size, directory_data, new_dir_size); free(directory_data); if (res == -1) { fprintf(stderr, "Unable to update directory contents of dir with id=0x%x!\n", directory->header.file_id); @@ -759,8 +759,8 @@ int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, return 0; } -int delete_file_from_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { - ccos_inode_t* parent_dir = ccos_get_parent_dir(ctx, file, image_data); +int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { + ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file, image_data); TRACE("Reading contents of the directory %*s (0x%x)", parent_dir->desc.name_length, parent_dir->desc.name, @@ -769,13 +769,13 @@ int delete_file_from_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* im size_t dir_size = 0; uint8_t* directory_data = NULL; - if (ccos_read_file(ctx, parent_dir, image_data, &directory_data, &dir_size) == -1) { + if (ccos_read_file(disk, parent_dir, image_data, &directory_data, &dir_size) == -1) { fprintf(stderr, "Unable to read directory contents at directory id 0x%x\n", parent_dir->header.file_id); return -1; } parsed_directory_element_t* elements = NULL; - if (parse_directory_data(ctx, image_data, directory_data, dir_size, parent_dir->desc.dir_count, &elements) == -1) { + if (parse_directory_data(disk, image_data, directory_data, dir_size, parent_dir->desc.dir_count, &elements) == -1) { fprintf(stderr, "Unable to add file to directory files list: Unable to parse directory data!\n"); free(directory_data); return -1; @@ -826,11 +826,11 @@ int delete_file_from_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* im size_t new_dir_size = dir_size - shrink_size; // Write dir contents back with old size to overwrite bytes at the end of dir with zeroes. - int res = ccos_write_file(ctx, parent_dir, image_data, image_size, directory_data, dir_size); + int res = ccos_write_file(disk, parent_dir, image_data, image_size, directory_data, dir_size); // Do that once more with new size to clear freed up content block. if (res != -1) { - res = ccos_write_file(ctx, parent_dir, image_data, image_size, directory_data, new_dir_size); + res = ccos_write_file(disk, parent_dir, image_data, image_size, directory_data, new_dir_size); } free(directory_data); @@ -845,7 +845,7 @@ int delete_file_from_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* im parent_dir->desc.dir_length = new_dir_size; parent_dir->desc.dir_count -= 1; - update_inode_checksums(ctx, parent_dir); + update_inode_checksums(disk, parent_dir); return 0; } @@ -923,9 +923,9 @@ int parse_file_name(const short_string_t* file_name, char* basename, char* type, return 0; } -int get_block_data(ccfs_handle ctx, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size) { - size_t block_size = get_block_size(ctx); - size_t log_block_size = get_log_block_size(ctx); +int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size) { + size_t block_size = get_block_size(disk); + size_t log_block_size = get_log_block_size(disk); // TODO: check bounds uint32_t address = block * block_size; *start = &(data[address + CCOS_DATA_OFFSET]); @@ -933,18 +933,18 @@ int get_block_data(ccfs_handle ctx, uint16_t block, const uint8_t* data, const u return 0; } -int get_free_blocks(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, +int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, uint16_t** free_blocks) { size_t free_count = 0; - size_t block_size = get_block_size(ctx); + size_t block_size = get_block_size(disk); size_t block_count = data_size / block_size; // sanity checks int allocated_info[MAX_BITMASK_BLOCKS_IN_IMAGE]; for (size_t i = 0; i < bitmask_list->length; i++) { allocated_info[i] = bitmask_list->bitmask_blocks[i]->allocated; - uint16_t checksum = calc_bitmask_checksum(ctx, bitmask_list->bitmask_blocks[i]); + uint16_t checksum = calc_bitmask_checksum(disk, bitmask_list->bitmask_blocks[i]); if (bitmask_list->bitmask_blocks[i]->checksum != checksum) { fprintf(stderr, "Warn: bitmask #" SIZE_T " checksum mismatch! Expected: 0x%x, got: 0x%x!\n", i, bitmask_list->bitmask_blocks[i]->checksum, checksum); @@ -970,7 +970,7 @@ int get_free_blocks(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, size_t d } for (size_t block = 0; block < bitmask_list->length; block++) { - for (int i = 0; i < get_bitmask_size(ctx); ++i) { + for (int i = 0; i < get_bitmask_size(disk); ++i) { uint8_t* bitmaks_bytes = get_bitmask_bytes(bitmask_list->bitmask_blocks[block]); if (bitmaks_bytes[i] != 0xFF) { uint8_t byte = bitmaks_bytes[i]; @@ -978,7 +978,7 @@ int get_free_blocks(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, size_t d if (!(byte & 1u)) { free_count++; if (free_count < *free_blocks_count) { - (*free_blocks)[free_count] = (block * get_bitmask_blocks(ctx)) + i * 8 + j; + (*free_blocks)[free_count] = (block * get_bitmask_blocks(disk)) + i * 8 + j; } } byte = byte >> 1u; @@ -1000,7 +1000,7 @@ int is_root_dir(const ccos_inode_t* file) { return file->header.file_id == file->desc.dir_file_id; } -int change_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date, date_type_t type) { +int change_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date, date_type_t type) { if (is_root_dir(file)) return -1; if (type == CREATED) { @@ -1012,6 +1012,6 @@ int change_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date, date_ } else { return -1; } - update_inode_checksums(ctx, file); + update_inode_checksums(disk, file); return 0; } diff --git a/ccos_private.h b/ccos_private.h index 2b006af..58e2da0 100644 --- a/ccos_private.h +++ b/ccos_private.h @@ -5,7 +5,7 @@ #ifndef CCOS_DISK_TOOL_CCOS_PRIVATE_H #define CCOS_DISK_TOOL_CCOS_PRIVATE_H -#include "ccos_context.h" +#include "ccos_disk.h" #include "ccos_structure.h" #include "string_utils.h" @@ -53,7 +53,7 @@ uint16_t calc_inode_metadata_checksum(const ccos_inode_t* inode); * * @return The file blocks section checksum. */ -uint16_t calc_inode_blocks_checksum(ccfs_handle ctx, const ccos_inode_t* inode); +uint16_t calc_inode_blocks_checksum(ccos_disk_t* disk, const ccos_inode_t* inode); /** * @brief Calculates the checksum of the content inode. @@ -63,7 +63,7 @@ uint16_t calc_inode_blocks_checksum(ccfs_handle ctx, const ccos_inode_t* inode); * * @return The content inode checksum. */ -uint16_t calc_content_inode_checksum(ccfs_handle ctx, const ccos_content_inode_t* content_inode); +uint16_t calc_content_inode_checksum(ccos_disk_t* disk, const ccos_content_inode_t* content_inode); /** * @brief Calculates the checksum of image's bitmask. @@ -73,7 +73,7 @@ uint16_t calc_content_inode_checksum(ccfs_handle ctx, const ccos_content_inode_t * * @return The bitmask checksum. */ -uint16_t calc_bitmask_checksum(ccfs_handle ctx, const ccos_bitmask_t* bitmask); +uint16_t calc_bitmask_checksum(ccos_disk_t* disk, const ccos_bitmask_t* bitmask); /** * @brief Recalculate checksums of the inode. @@ -81,7 +81,7 @@ uint16_t calc_bitmask_checksum(ccfs_handle ctx, const ccos_bitmask_t* bitmask); * @param[in] ctx Filesystem context handle. * @param inode The inode. */ -void update_inode_checksums(ccfs_handle ctx, ccos_inode_t* inode); +void update_inode_checksums(ccos_disk_t* disk, ccos_inode_t* inode); /** * @brief Recalculate checksum of the content inode. @@ -89,7 +89,7 @@ void update_inode_checksums(ccfs_handle ctx, ccos_inode_t* inode); * @param[in] ctx Filesystem context handle. * @param content_inode The content inode. */ -void update_content_inode_checksums(ccfs_handle ctx, ccos_content_inode_t* content_inode); +void update_content_inode_checksums(ccos_disk_t* disk, ccos_content_inode_t* content_inode); /** * @brief Re-calculate and update CCOS image bitmask checksum. @@ -97,7 +97,7 @@ void update_content_inode_checksums(ccfs_handle ctx, ccos_content_inode_t* conte * @param[in] ctx Filesystem context handle. * @param bitmask CCOS image bitmask. */ -void update_bitmask_checksum(ccfs_handle ctx, ccos_bitmask_t* bitmask); +void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask); /** * @brief Find a superblock (i.e. the inode with the root directory description) in a CCOS filesystem image. @@ -110,7 +110,7 @@ void update_bitmask_checksum(ccfs_handle ctx, ccos_bitmask_t* bitmask); * @return 0 on success, with superblock numper passed out to the superblock parameter, -1 on error (i.e. in case of * invalid image format). */ -int get_superblock(ccfs_handle ctx, const uint8_t* data, size_t image_size, uint16_t* superblock); +int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, uint16_t* superblock); /** * @brief Get the CCOS filesystem inode at the given block. @@ -121,7 +121,7 @@ int get_superblock(ccfs_handle ctx, const uint8_t* data, size_t image_size, uint * * @return Pointer to CCOS filesystem inode structure. */ -ccos_inode_t* get_inode(ccfs_handle ctx, uint16_t block, const uint8_t* data); +ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data); /** * @brief Parse an inode and return the list of the file content blocks. @@ -134,7 +134,7 @@ ccos_inode_t* get_inode(ccfs_handle ctx, uint16_t block, const uint8_t* data); * * @return 0 on success, -1 otherwise. */ -int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks); +int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks); /** * @brief Get all bitmask blocks from the image. @@ -145,7 +145,7 @@ int get_file_blocks(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, si * * @return List of CCOS image bitmask blocks. */ -ccos_bitmask_list_t find_bitmask_blocks(ccfs_handle ctx, uint8_t* data, size_t data_size); +ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk, uint8_t* data, size_t data_size); /** * @brief Find available free block in the image and return it's number. @@ -155,7 +155,7 @@ ccos_bitmask_list_t find_bitmask_blocks(ccfs_handle ctx, uint8_t* data, size_t d * * @return The free block on success, CCOS_INVALID_BLOCK if no free space in the image. */ -uint16_t get_free_block(ccfs_handle ctx, const ccos_bitmask_list_t* bitmask_list); +uint16_t get_free_block(ccos_disk_t* disk, const ccos_bitmask_list_t* bitmask_list); /** * @brief Mark block in the bitmask as free or used. @@ -165,7 +165,7 @@ uint16_t get_free_block(ccfs_handle ctx, const ccos_bitmask_list_t* bitmask_list * @param[in] block The number of the block. * @param[in] mode The mode (0 for free, 1 for used). */ -void mark_block(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, uint16_t block, uint8_t mode); +void mark_block(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, uint16_t block, uint8_t mode); /** * @brief Initialize inode at the given block. @@ -177,7 +177,7 @@ void mark_block(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, uint16_t blo * * @return Pointer to the newly created inode on success, NULL otherwise. */ -ccos_inode_t* init_inode(ccfs_handle ctx, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data); +ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data); /** * @brief Adds a new content inode (block with file block data) to the content inode list of the given file. @@ -189,7 +189,7 @@ ccos_inode_t* init_inode(ccfs_handle ctx, uint16_t block, uint16_t parent_dir_bl * * @return New content inode on success, NULL otherwise. */ -ccos_content_inode_t* add_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); /** * @brief Get content inode at the given block number. @@ -200,7 +200,7 @@ ccos_content_inode_t* add_content_inode(ccfs_handle ctx, ccos_inode_t* file, uin * * @return The content inode. */ -ccos_content_inode_t* get_content_inode(ccfs_handle ctx, uint16_t block, const uint8_t* data); +ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data); /** * @brief Gets the last content inode in the content inode list of the given file. @@ -211,7 +211,7 @@ ccos_content_inode_t* get_content_inode(ccfs_handle ctx, uint16_t block, const u * * @return The last content inode on success, NULL otherwise. */ -ccos_content_inode_t* get_last_content_inode(ccfs_handle ctx, const ccos_inode_t* file, const uint8_t* image_data); +ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file, const uint8_t* image_data); /** * @brief Cleanup image block at the given number and mark it as empty both in the image and in the image bitmask. @@ -221,7 +221,7 @@ ccos_content_inode_t* get_last_content_inode(ccfs_handle ctx, const ccos_inode_t * @param image CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. */ -void erase_block(ccfs_handle ctx, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list); +void erase_block(ccos_disk_t* disk, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list); /** * @brief Removes the last content inode from the file's content inodes list, and erases this content inode block. @@ -233,7 +233,7 @@ void erase_block(ccfs_handle ctx, uint16_t block, uint8_t* image, ccos_bitmask_l * * @return 0 on success, -1 otherwise. */ -int remove_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); /** * @brief Removes last content block from the file. @@ -245,7 +245,7 @@ int remove_content_inode(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, cco * * @return 0 on success, -1 otherwise. */ -int remove_block_from_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); /** * @brief Adds content block to the file. @@ -257,7 +257,7 @@ int remove_block_from_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c * * @return Block number of the added block on success, CCOS_INVALID_BLOCK otherwise. */ -uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); /** * @brief Add new file entry to the list of files in the given directory. @@ -270,7 +270,7 @@ uint16_t add_block_to_file(ccfs_handle ctx, ccos_inode_t* file, uint8_t* data, c * * @return 0 on success, -1 otherwise. */ -int add_file_to_directory(ccfs_handle ctx, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size); +int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size); /** * @brief Insert new directory entry into the directory, effectively making this directory a parent for the given @@ -284,7 +284,7 @@ int add_file_to_directory(ccfs_handle ctx, ccos_inode_t* directory, ccos_inode_t * * @return 0 on success, -1 otherwise. */ -int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, +int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, uint8_t* image_data, size_t image_size, ccos_inode_t* file); @@ -299,7 +299,7 @@ int add_file_entry_to_dir_contents(ccfs_handle ctx, ccos_inode_t* directory, * * @return 0 on success, -1 otherwise. */ -int delete_file_from_parent_dir(ccfs_handle ctx, ccos_inode_t* file, uint8_t* image_data, size_t image_size); +int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size); /** * @brief Perse CCOS file name and return it's basename and it's type. @@ -327,7 +327,7 @@ int parse_file_name(const short_string_t* file_name, char* basename, char* type, * * @return 0 on success, -1 otherwise. */ -int parse_directory_data(ccfs_handle ctx, uint8_t* image_data, +int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, const uint8_t* directory_data, size_t directory_data_size, uint16_t entry_count, parsed_directory_element_t** entries); @@ -343,7 +343,7 @@ int parse_directory_data(ccfs_handle ctx, uint8_t* image_data, * * @return 0 on success, -1 otherwise. */ -int get_block_data(ccfs_handle ctx, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size); +int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size); /** * @brief Return info about free blocks in a CCOS image. @@ -356,7 +356,7 @@ int get_block_data(ccfs_handle ctx, uint16_t block, const uint8_t* data, const u * * @return 0 on success, -1 otherwise. */ -int get_free_blocks(ccfs_handle ctx, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, +int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, uint16_t** free_blocks); /** @@ -390,6 +390,6 @@ int is_root_dir(const ccos_inode_t* file); * * @return 0 on success, -1 otherwise. */ -int change_date(ccfs_handle ctx, ccos_inode_t* file, ccos_date_t new_date, date_type_t type); +int change_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_date, date_type_t type); #endif // CCOS_DISK_TOOL_CCOS_PRIVATE_H diff --git a/ccos_structure.c b/ccos_structure.c index 807ce2b..8fc858c 100644 --- a/ccos_structure.c +++ b/ccos_structure.c @@ -1,8 +1,8 @@ #include "ccos_structure.h" #define SECTOR_SIZE_TO_CONST(name, X) \ - size_t get_##name (ccfs_handle ctx) { \ - switch (ctx->sector_size) { \ + size_t get_##name (ccos_disk_t* disk) { \ + switch (disk->sector_size) { \ case 256: return BS256_##X; \ case 512: return BS512_##X; \ default: return SIZE_MAX; \ diff --git a/ccos_structure.h b/ccos_structure.h index a1e58d0..bc99ffe 100644 --- a/ccos_structure.h +++ b/ccos_structure.h @@ -3,7 +3,7 @@ #include #include -#include "ccos_context.h" +#include "ccos_disk.h" #if __STDC_VERSION__ >= 201112L #include @@ -223,14 +223,14 @@ typedef struct { } dir_entry_t; #pragma pack(pop) -size_t get_block_size(ccfs_handle ctx); -size_t get_log_block_size(ccfs_handle ctx); -size_t get_inode_max_blocks(ccfs_handle ctx); -size_t get_content_inode_padding(ccfs_handle ctx); -size_t get_content_inode_max_blocks(ccfs_handle ctx); -size_t get_bitmask_size(ccfs_handle ctx); -size_t get_bitmask_blocks(ccfs_handle ctx); -size_t get_dir_default_size(ccfs_handle ctx); +size_t get_block_size(ccos_disk_t* disk); +size_t get_log_block_size(ccos_disk_t* disk); +size_t get_inode_max_blocks(ccos_disk_t* disk); +size_t get_content_inode_padding(ccos_disk_t* disk); +size_t get_content_inode_max_blocks(ccos_disk_t* disk); +size_t get_bitmask_size(ccos_disk_t* disk); +size_t get_bitmask_blocks(ccos_disk_t* disk); +size_t get_dir_default_size(ccos_disk_t* disk); uint16_t* get_inode_content_blocks(ccos_inode_t* inode); uint16_t* get_content_inode_content_blocks(ccos_content_inode_t* inode); diff --git a/main.c b/main.c index 10cffc9..edba475 100644 --- a/main.c +++ b/main.c @@ -4,7 +4,7 @@ #include #include "common.h" -#include "ccos_context.h" +#include "ccos_disk.h" #include "ccos_private.h" #include "ccos_image.h" #include "wrapper.h" @@ -94,20 +94,20 @@ static void print_usage() { "-l, --in-place Write changes to the original image\n"); } -ccfs_context_t* default_ccos_context() { - ccfs_context_t* ctx = malloc(sizeof(ccfs_context_t)); +ccos_disk_t* default_ccos_context() { + ccos_disk_t* disk = malloc(sizeof(ccos_disk_t)); - ctx->sector_size = DEFAULT_SECTOR_SIZE; - ctx->superblock_id = DEFAULT_SUPERBLOCK; - ctx->bitmap_block_id = DEFAULT_BITMASK_BLOCK_ID; + disk->sector_size = DEFAULT_SECTOR_SIZE; + disk->superblock_fid = DEFAULT_SUPERBLOCK; + disk->bitmap_fid = DEFAULT_BITMASK_BLOCK_ID; - return ctx; + return disk; } int main(int argc, char** argv) { op_mode_t mode = 0; char* path = NULL; - ccfs_context_t* ctx = default_ccos_context(); + ccos_disk_t* disk = default_ccos_context(); char* filename = NULL; char* dir_name = NULL; char* target_name = NULL; @@ -186,7 +186,7 @@ int main(int argc, char** argv) { mode = MODE_CREATE_BLANK; new_image_size = strtol(optarg, NULL, 10); - if (new_image_size <= 0 || new_image_size % ctx->sector_size != 0) { + if (new_image_size <= 0 || new_image_size % disk->sector_size != 0) { printf("Invalid image size! Value must be positive and a multiple of the sector size\n"); return 1; } @@ -204,7 +204,7 @@ int main(int argc, char** argv) { case SECTOR_SIZE_OPT: { long sector_size = strtol(optarg, NULL, 10); if (sector_size == 256 || sector_size == 512) { - ctx->sector_size = sector_size; + disk->sector_size = sector_size; break; } else { printf("Invalid sector size! Allowed only 256 or 512\n"); @@ -214,8 +214,8 @@ int main(int argc, char** argv) { case SUPERBLOCK_OPT: { long value = strtol(optarg, NULL, 16); if (0 < value && value < 0xFFFF) { - ctx->superblock_id = value; - ctx->bitmap_block_id = value - 1; + disk->superblock_fid = value; + disk->bitmap_fid = value - 1; break; } else { printf("Invalid superblock! Value must be in range 0x0001-0xFFFE\n"); @@ -226,10 +226,10 @@ int main(int argc, char** argv) { } TRACE("Use image '%s' with sector size %d, superblock %#x, bitmap block %#x", - path, ctx->sector_size, ctx->superblock_id, ctx->bitmap_block_id); + path, disk->sector_size, disk->superblock_fid, disk->bitmap_fid); if (mode == MODE_CREATE_BLANK) { - return create_blank_image(ctx, path, new_image_size); + return create_blank_image(disk, path, new_image_size); } uint8_t* file_contents = NULL; @@ -249,27 +249,27 @@ int main(int argc, char** argv) { int res; switch (mode) { case MODE_PRINT: { - res = print_image_info(ctx, path, file_contents, file_size, short_format); + res = print_image_info(disk, path, file_contents, file_size, short_format); if (res == 0) { - size_t free_bytes = ccos_calc_free_space(ctx, file_contents, file_size); + size_t free_bytes = ccos_calc_free_space(disk, file_contents, file_size); printf("Free space: " SIZE_T " bytes.\n", free_bytes); } break; } case MODE_DUMP: { - res = dump_image(ctx, path, file_contents, file_size); + res = dump_image(disk, path, file_contents, file_size); break; } case MODE_REPLACE_FILE: { - res = replace_file(ctx, path, filename, target_name, file_contents, file_size, in_place); + res = replace_file(disk, path, filename, target_name, file_contents, file_size, in_place); break; } case MODE_COPY_FILE: { - res = copy_file(ctx, target_image, filename, file_contents, file_size, in_place); + res = copy_file(disk, target_image, filename, file_contents, file_size, in_place); break; } case MODE_DELETE_FILE: { - res = delete_file(ctx, path, filename, in_place); + res = delete_file(disk, path, filename, in_place); break; } case MODE_ADD_FILE: { @@ -278,16 +278,16 @@ int main(int argc, char** argv) { print_usage(); res = -1; } else { - res = add_file(ctx, path, filename, target_name, file_contents, file_size, in_place); + res = add_file(disk, path, filename, target_name, file_contents, file_size, in_place); } break; } case MODE_CREATE_DIRECTORY: { - res = create_directory(ctx, path, dir_name, file_contents, file_size, in_place); + res = create_directory(disk, path, dir_name, file_contents, file_size, in_place); break; } case MODE_RENAME_FILE: { - res = rename_file(ctx, path, filename, target_name, file_contents, file_size, in_place); + res = rename_file(disk, path, filename, target_name, file_contents, file_size, in_place); break; } default: { diff --git a/tests/format_test.c b/tests/format_test.c index 84851dc..ad25f0d 100644 --- a/tests/format_test.c +++ b/tests/format_test.c @@ -12,7 +12,7 @@ #include #include #include -#include "ccos_context.h" +#include "ccos_disk.h" #include "ccos_format.h" static void display_bad_sector(const uint8_t* actual, size_t sector_size) { diff --git a/wrapper.c b/wrapper.c index 062b50f..a2d113c 100644 --- a/wrapper.c +++ b/wrapper.c @@ -8,7 +8,7 @@ #include #include #include -#include "ccos_context.h" +#include "ccos_disk.h" #include "ccos_format.h" #define PROGRAMS_DIR_1 "Programs~Subject~" @@ -23,9 +23,9 @@ struct stat statbuf; typedef enum { RESULT_OK = 1, RESULT_ERROR, RESULT_BREAK } traverse_callback_result_t; -typedef traverse_callback_result_t (*on_file_t)(ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, const char* dirname, int level, void* arg); +typedef traverse_callback_result_t (*on_file_t)(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, const char* dirname, int level, void* arg); -typedef traverse_callback_result_t (*on_dir_t)(ccfs_handle ctx, ccos_inode_t* dir, const uint8_t* data, const char* dirname, int level, void* arg); +typedef traverse_callback_result_t (*on_dir_t)(ccos_disk_t* disk, ccos_inode_t* dir, const uint8_t* data, const char* dirname, int level, void* arg); static char* format_version(version_t* version) { char* version_string = (char*)calloc(VERSION_MAX_SIZE, sizeof(char)); @@ -37,11 +37,11 @@ static char* format_version(version_t* version) { return version_string; } -static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data, const char* dirname, int level, +static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, const char* dirname, int level, on_file_t on_file, on_dir_t on_dir, void* arg) { uint16_t files_count = 0; ccos_inode_t** dir_contents = NULL; - if (ccos_get_dir_contents(ctx, dir, data, &files_count, &dir_contents) == -1) { + if (ccos_get_dir_contents(disk, dir, data, &files_count, &dir_contents) == -1) { fprintf(stderr, "Unable to get root dir contents!\n"); return -1; } @@ -53,7 +53,7 @@ static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data const ccos_inode_t* inode = dir_contents[i]; - ccos_validate_file(ctx, inode); + ccos_validate_file(disk, inode); if (ccos_is_dir(dir_contents[i])) { TRACE("%d: directory", i + 1); @@ -77,7 +77,7 @@ static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data if (on_dir != NULL) { traverse_callback_result_t res; - if ((res = on_dir(ctx, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { + if ((res = on_dir(disk, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { TRACE("on_dir returned %d", res); free(dir_contents); free(subdir); @@ -90,7 +90,7 @@ static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data } } - int res = traverse_ccos_image(ctx, dir_contents[i], data, subdir, level + 1, on_file, on_dir, arg); + int res = traverse_ccos_image(disk, dir_contents[i], data, subdir, level + 1, on_file, on_dir, arg); free(subdir); if (res == -1) { @@ -102,7 +102,7 @@ static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data if (on_file != NULL) { traverse_callback_result_t res; - if ((res = on_file(ctx, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { + if ((res = on_file(disk, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { TRACE("on_file returned %d", res); free(dir_contents); if (res == RESULT_ERROR) { @@ -122,7 +122,7 @@ static int traverse_ccos_image(ccfs_handle ctx, ccos_inode_t* dir, uint8_t* data } static traverse_callback_result_t print_file_info( - ccfs_handle ctx, ccos_inode_t* file, UNUSED const uint8_t* data, + ccos_disk_t* disk, ccos_inode_t* file, UNUSED const uint8_t* data, UNUSED const char* dirname, int level, void* arg ) { int short_format = *(int*)arg; @@ -180,8 +180,8 @@ static traverse_callback_result_t print_file_info( return RESULT_OK; } -int print_image_info(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size, int short_format) { - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, data_size); +int print_image_info(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, int short_format) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); if (root_dir == NULL) { fprintf(stderr, "Unable to print image info: Unable to find root directory!\n"); return -1; @@ -218,11 +218,11 @@ int print_image_info(ccfs_handle ctx, const char* path, uint8_t* data, size_t da print_frame(128); } - return traverse_ccos_image(ctx, root_dir, data, "", 0, print_file_info, print_file_info, &short_format); + return traverse_ccos_image(disk, root_dir, data, "", 0, print_file_info, print_file_info, &short_format); } static traverse_callback_result_t dump_dir_tree_on_file( - ccfs_handle ctx, ccos_inode_t* file, const uint8_t* data, const char* dirname, + ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, const char* dirname, UNUSED int level, UNUSED void* arg ) { char* abspath = (char*)calloc(sizeof(char), PATH_MAX); @@ -245,7 +245,7 @@ static traverse_callback_result_t dump_dir_tree_on_file( size_t file_size = 0; uint8_t* file_data = NULL; - if (ccos_read_file(ctx, file, data, &file_data, &file_size) == -1) { + if (ccos_read_file(disk, file, data, &file_data, &file_size) == -1) { fprintf(stderr, "Unable to dump file at 0x%x: Unable to get file contents!\n", ccos_file_id(file)); if (file_data != NULL) { free(file_data); @@ -281,7 +281,7 @@ static traverse_callback_result_t dump_dir_tree_on_file( } static traverse_callback_result_t dump_dir_tree_on_dir( - ccfs_handle ctx, ccos_inode_t* dir, UNUSED const uint8_t* data, + ccos_disk_t* disk, ccos_inode_t* dir, UNUSED const uint8_t* data, const char* dirname, UNUSED int level, UNUSED void* arg ) { char subdir_name[CCOS_MAX_FILE_NAME]; @@ -320,24 +320,24 @@ static traverse_callback_result_t dump_dir_tree_on_dir( return RESULT_OK; } -int dump_image(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size) { - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, data_size); +int dump_image(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); if (root_dir == NULL) { fprintf(stderr, "Unable to dump image: Unable to get root directory!\n"); return -1; } - return dump_dir(ctx, path, root_dir, data); + return dump_dir(disk, path, root_dir, data); } -int dump_file(ccfs_handle ctx, const char* path_to_dir, ccos_inode_t* file, uint8_t* image_data) { +int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, uint8_t* image_data) { char dir_name[CCOS_MAX_FILE_NAME]; memset(dir_name, 0, CCOS_MAX_FILE_NAME); char dir_type[CCOS_MAX_FILE_NAME]; memset(dir_type, 0, CCOS_MAX_FILE_NAME); ccos_parse_file_name(file, dir_name, dir_type, NULL, NULL); - traverse_callback_result_t res = dump_dir_tree_on_file(ctx, file, image_data, path_to_dir, 0, NULL); + traverse_callback_result_t res = dump_dir_tree_on_file(disk, file, image_data, path_to_dir, 0, NULL); if (res == RESULT_ERROR) { fprintf(stderr, "Unable to dump file \"%s~%s\": %s!\n", dir_name, dir_type, strerror(errno)); @@ -347,9 +347,9 @@ int dump_file(ccfs_handle ctx, const char* path_to_dir, ccos_inode_t* file, uint return 0; } -int dump_dir(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data) { +int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data) { char* name_trimmed; - if (dir == ccos_get_parent_dir(ctx, dir, data)) { + if (dir == ccos_get_parent_dir(disk, dir, data)) { name_trimmed = strdup(short_string_to_string(ccos_get_file_name(dir))); if (strcmp(name_trimmed, "")) { int sz = strlen(name_trimmed); @@ -402,25 +402,25 @@ int dump_dir(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data } } - int res = traverse_ccos_image(ctx, dir, data, dirname, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); + int res = traverse_ccos_image(disk, dir, data, dirname, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); free(dirname); TRACE("Image dump complete!"); return res; } -int dump_image_to(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size, const char* destpath) { - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, data_size); +int dump_image_to(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, const char* destpath) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); if (root_dir == NULL) { fprintf(stderr, "Unable to dump image: Unable to get root directory!\n"); return -1; } - return dump_dir_to(ctx, path, root_dir, data, destpath); + return dump_dir_to(disk, path, root_dir, data, destpath); } -int dump_dir_to(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath) { +int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath) { char* name_trimmed; - if (dir == ccos_get_parent_dir(ctx, dir, data)) { + if (dir == ccos_get_parent_dir(disk, dir, data)) { name_trimmed = strdup(short_string_to_string(ccos_get_file_name(dir))); if (strcmp(name_trimmed, "")) { int sz = strlen(name_trimmed); @@ -483,14 +483,14 @@ int dump_dir_to(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* d } } - int res = traverse_ccos_image(ctx, dir, data, dest, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); + int res = traverse_ccos_image(disk, dir, data, dest, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); free(dest); TRACE("Image dump complete!"); return res; } static traverse_callback_result_t find_file_on_file( - ccfs_handle ctx, ccos_inode_t* file, UNUSED const uint8_t* data, + ccos_disk_t* disk, ccos_inode_t* file, UNUSED const uint8_t* data, UNUSED const char* dirname, UNUSED int level, void* arg ) { char* file_name = short_string_to_string(ccos_get_file_name(file)); @@ -511,11 +511,11 @@ static traverse_callback_result_t find_file_on_file( return RESULT_OK; } -static int find_filename(ccfs_handle ctx, ccos_inode_t* root_dir, uint8_t* data, const char* filename, ccos_inode_t** file, +static int find_filename(ccos_disk_t* disk, ccos_inode_t* root_dir, uint8_t* data, const char* filename, ccos_inode_t** file, int verbose) { find_file_data_t find_file_data = {.target_name = filename, .target_file = 0}; - if (traverse_ccos_image(ctx, root_dir, data, "", 0, find_file_on_file, find_file_on_file, &find_file_data) == -1) { + if (traverse_ccos_image(disk, root_dir, data, "", 0, find_file_on_file, find_file_on_file, &find_file_data) == -1) { fprintf(stderr, "Unable to find file in image: Unable to complete search!\n"); return -1; } @@ -531,7 +531,7 @@ static int find_filename(ccfs_handle ctx, ccos_inode_t* root_dir, uint8_t* data, return 0; } -int replace_file(ccfs_handle ctx, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, +int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, int in_place) { const char* basename; @@ -541,10 +541,10 @@ int replace_file(ccfs_handle ctx, const char* path, const char* filename, const basename = get_basename(path); } - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, data_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); ccos_inode_t* found_file = NULL; - if (find_filename(ctx, root_dir, data, basename, &found_file, 1) != 0) { + if (find_filename(disk, root_dir, data, basename, &found_file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", basename); return -1; } @@ -576,7 +576,7 @@ int replace_file(ccfs_handle ctx, const char* path, const char* filename, const return -1; } - if (ccos_replace_file(ctx, found_file, file_contents, file_size, data) == -1) { + if (ccos_replace_file(disk, found_file, file_contents, file_size, data) == -1) { fprintf(stderr, "Unable to overwrite file %s in the image!\n", filename); free(file_contents); return -1; @@ -611,25 +611,25 @@ int replace_file(ccfs_handle ctx, const char* path, const char* filename, const return 0; } -static int do_copy_file(ccfs_handle ctx, uint8_t* dest_data, size_t dest_size, ccos_inode_t* dest_root_dir, uint8_t* source_data, +static int do_copy_file(ccos_disk_t* disk, uint8_t* dest_data, size_t dest_size, ccos_inode_t* dest_root_dir, uint8_t* source_data, ccos_inode_t* source_root_dir, const char* filename) { ccos_inode_t* source_file = NULL; - if (find_filename(ctx, source_root_dir, source_data, filename, &source_file, 1) != 0) { + if (find_filename(disk, source_root_dir, source_data, filename, &source_file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", filename); return -1; } - const ccos_inode_t* source_parent_dir = ccos_get_parent_dir(ctx, source_file, source_data); + const ccos_inode_t* source_parent_dir = ccos_get_parent_dir(disk, source_file, source_data); char* source_dir_name = short_string_to_string(ccos_get_file_name(source_parent_dir)); ccos_inode_t* dest_directory = NULL; - if (find_filename(ctx, dest_root_dir, dest_data, source_dir_name, &dest_directory, 1) == -1) { + if (find_filename(disk, dest_root_dir, dest_data, source_dir_name, &dest_directory, 1) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will copy to the " PROGRAMS_DIR_1 " instead.\n", source_dir_name); - if (find_filename(ctx, dest_root_dir, dest_data, PROGRAMS_DIR_1, &dest_directory, 0) == -1 && - find_filename(ctx, dest_root_dir, dest_data, PROGRAMS_DIR_2, &dest_directory, 0) == -1) { + if (find_filename(disk, dest_root_dir, dest_data, PROGRAMS_DIR_1, &dest_directory, 0) == -1 && + find_filename(disk, dest_root_dir, dest_data, PROGRAMS_DIR_2, &dest_directory, 0) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will copy to the root directory instead\n", PROGRAMS_DIR_1); dest_directory = dest_root_dir; @@ -638,10 +638,10 @@ static int do_copy_file(ccfs_handle ctx, uint8_t* dest_data, size_t dest_size, c free(source_dir_name); - return ccos_copy_file(ctx, dest_data, dest_size, dest_directory, source_data, source_file); + return ccos_copy_file(disk, dest_data, dest_size, dest_directory, source_data, source_file); } -int copy_file(ccfs_handle ctx, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place) { +int copy_file(ccos_disk_t* disk, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place) { if (target_image == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -660,20 +660,20 @@ int copy_file(ccfs_handle ctx, const char* target_image, const char* filename, u } ccos_inode_t* root_dir; - if ((root_dir = ccos_get_root_dir(ctx, source_data, source_size)) == NULL) { + if ((root_dir = ccos_get_root_dir(disk, source_data, source_size)) == NULL) { fprintf(stderr, "Unable to get root directory of the source image!\n"); free(dest_data); return -1; } ccos_inode_t* dest_root_dir; - if ((dest_root_dir = (ccos_inode_t*)ccos_get_root_dir(ctx, dest_data, dest_size)) == NULL) { + if ((dest_root_dir = (ccos_inode_t*)ccos_get_root_dir(disk, dest_data, dest_size)) == NULL) { fprintf(stderr, "Unable to get root directory of the target image!\n"); free(dest_data); return -1; } - if (do_copy_file(ctx, dest_data, dest_size, dest_root_dir, source_data, root_dir, filename) == -1) { + if (do_copy_file(disk, dest_data, dest_size, dest_root_dir, source_data, root_dir, filename) == -1) { fprintf(stderr, "Unable to copy file \"%s\" in \"%s\"!\n", filename, target_image); free(dest_data); return -1; @@ -684,7 +684,7 @@ int copy_file(ccfs_handle ctx, const char* target_image, const char* filename, u return res; } -int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, const char* file_name, +int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, uint8_t* data, size_t data_size, int in_place) { if (image_path == NULL) { fprintf(stderr, "No path to image is provided to copy file to!\n"); @@ -703,7 +703,7 @@ int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, con return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, data_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); if (root_dir == NULL) { fprintf(stderr, "Unable to add file to image: Unable to get root directory!\n"); free(file_data); @@ -712,14 +712,14 @@ int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, con ccos_inode_t* dest_dir = NULL; - if (find_filename(ctx, root_dir, data, PROGRAMS_DIR_1, &dest_dir, 0) == -1 && - find_filename(ctx, root_dir, data, PROGRAMS_DIR_2, &dest_dir, 0) == -1) { + if (find_filename(disk, root_dir, data, PROGRAMS_DIR_1, &dest_dir, 0) == -1 && + find_filename(disk, root_dir, data, PROGRAMS_DIR_2, &dest_dir, 0) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will add file to the root directory instead\n", PROGRAMS_DIR_1); dest_dir = root_dir; } - ccos_inode_t* new_file = ccos_add_file(ctx, dest_dir, file_data, file_size, file_name, data, data_size); + ccos_inode_t* new_file = ccos_add_file(disk, dest_dir, file_data, file_size, file_name, data, data_size); free(file_data); if (new_file == NULL) { fprintf(stderr, "Unable to copy %s to %s!\n", file_name, file_path); @@ -729,7 +729,7 @@ int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, con return save_image(image_path, data, data_size, in_place); } -int delete_file(ccfs_handle ctx, const char* path, const char* filename, int in_place) { +int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int in_place) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -747,15 +747,15 @@ int delete_file(ccfs_handle ctx, const char* path, const char* filename, int in_ return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, data, size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, size); ccos_inode_t* file = NULL; - if (find_filename(ctx, root_dir, data, filename, &file, 1) != 0) { + if (find_filename(disk, root_dir, data, filename, &file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", filename); free(data); return -1; } - if (ccos_delete_file(ctx, data, size, file) == -1) { + if (ccos_delete_file(disk, data, size, file) == -1) { fprintf(stderr, "Unable to delete file %s!\n", filename); free(data); return -1; @@ -766,7 +766,7 @@ int delete_file(ccfs_handle ctx, const char* path, const char* filename, int in_ return res; } -int create_directory(ccfs_handle ctx, char* path, char* directory_name, uint8_t* image_data, size_t image_size, int in_place) { +int create_directory(ccos_disk_t* disk, char* path, char* directory_name, uint8_t* image_data, size_t image_size, int in_place) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -777,13 +777,13 @@ int create_directory(ccfs_handle ctx, char* path, char* directory_name, uint8_t* return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, image_data, image_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk, image_data, image_size); if (root_dir == NULL) { fprintf(stderr, "Unable to add file to image: Unable to get root directory!\n"); return -1; } - if (ccos_create_dir(ctx, root_dir, directory_name, image_data, image_size) == NULL) { + if (ccos_create_dir(disk, root_dir, directory_name, image_data, image_size) == NULL) { fprintf(stderr, "Unable to create directory!\n"); return -1; } @@ -791,7 +791,7 @@ int create_directory(ccfs_handle ctx, char* path, char* directory_name, uint8_t* return save_image(path, image_data, image_size, in_place); } -int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place) { +int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -807,19 +807,19 @@ int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, ui return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(ctx, image_data, image_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk, image_data, image_size); if (root_dir == NULL) { fprintf(stderr, "Unable to rename file: Unable to get root directory!\n"); return -1; } ccos_inode_t* file = NULL; - if (find_filename(ctx, root_dir, image_data, file_name, &file, 1) != 0) { + if (find_filename(disk, root_dir, image_data, file_name, &file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", file_name); return -1; } - if (ccos_rename_file(ctx, image_data, image_size, file, new_name, NULL) == -1) { + if (ccos_rename_file(disk, image_data, image_size, file, new_name, NULL) == -1) { char* old_file_name = short_string_to_string(ccos_get_file_name(file)); fprintf(stderr, "Unable to rename file %s to %s!\n", old_file_name, new_name); free(old_file_name); @@ -830,27 +830,25 @@ int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, ui return res; } -int create_blank_image(ccfs_handle ctx, char* path, size_t size) { +int create_blank_image(ccos_disk_t* disk, char* path, size_t size) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return EINVAL; } - if (size % ctx->sector_size != 0) { - fprintf(stderr, "Image size must be a multiple of the sector size %d\n", ctx->sector_size); + if (size % disk->sector_size != 0) { + fprintf(stderr, "Image size must be a multiple of the sector size %d\n", disk->sector_size); return EINVAL; } - ccos_disk_t disk; - - disk_format_t format = ctx->sector_size == 256 ? CCOS_DISK_FORMAT_BUBMEM : CCOS_DISK_FORMAT_COMPASS; - int res = ccos_new_disk_image(format, size, &disk); + disk_format_t format = disk->sector_size == 256 ? CCOS_DISK_FORMAT_BUBMEM : CCOS_DISK_FORMAT_COMPASS; + int res = ccos_new_disk_image(format, size, disk); if (res) { fprintf(stderr, "Failed to create new disk image. Error code: %s\n", strerror(res)); return res; } - res = save_image(path, disk.data, disk.size, 1); - free(disk.data); + res = save_image(path, disk->data, disk->size, 1); + free(disk->data); return res; } diff --git a/wrapper.h b/wrapper.h index 12915bd..00a8be5 100644 --- a/wrapper.h +++ b/wrapper.h @@ -1,6 +1,9 @@ #ifndef WRAPPER_H #define WRAPPER_H +#include "ccos_disk.h" +#include "ccos_structure.h" + #include /** @@ -13,7 +16,7 @@ * * @return 0 on success, -1 otherwise. */ -int dump_dir(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data); +int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data); /** * @brief Dumps all files and directories from CCOS disk image. @@ -25,7 +28,7 @@ int dump_dir(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data * * @return 0 on success, -1 otherwise. */ -int dump_image(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size); +int dump_image(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size); /** * @brief Dumps file to directory from CCOS disk image. @@ -37,7 +40,7 @@ int dump_image(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_siz * * @return 0 on success, -1 otherwise. */ -int dump_file(ccfs_handle ctx, const char* path_to_dir, ccos_inode_t* file, uint8_t* image_data); +int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, uint8_t* image_data); /** * @brief Dumps a directory recursively from CCOS disk image to a custom folder. @@ -50,7 +53,7 @@ int dump_file(ccfs_handle ctx, const char* path_to_dir, ccos_inode_t* file, uint * * @return 0 on success, -1 otherwise. */ -int dump_dir_to(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath); +int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath); /** * @brief Dumps all files and directories from CCOS disk image to a custom folder. @@ -63,7 +66,7 @@ int dump_dir_to(ccfs_handle ctx, const char* path, ccos_inode_t* dir, uint8_t* d * * @return 0 on success, -1 otherwise. */ -int dump_image_to(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size, const char* destpath); +int dump_image_to(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, const char* destpath); /** * @brief Prints a CCOS image contents. @@ -76,7 +79,7 @@ int dump_image_to(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_ * * @return 0 on success, -1 otherwise. */ -int print_image_info(ccfs_handle ctx, const char* path, uint8_t* data, size_t data_size, int short_format); +int print_image_info(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, int short_format); /** * @brief Replace file in the CCOS image. @@ -93,7 +96,7 @@ int print_image_info(ccfs_handle ctx, const char* path, uint8_t* data, size_t da * * @return 0 on success, -1 otherwise. */ -int replace_file(ccfs_handle ctx, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, +int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, int in_place); /** @@ -109,7 +112,7 @@ int replace_file(ccfs_handle ctx, const char* path, const char* filename, const * * @return 0 on success, -1 otherwise. */ -int copy_file(ccfs_handle ctx, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place); +int copy_file(ccos_disk_t* disk, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place); /** * @brief Delete file in the image. @@ -122,7 +125,7 @@ int copy_file(ccfs_handle ctx, const char* target_image, const char* filename, u * * @return 0 on success, -1 otherwise. */ -int delete_file(ccfs_handle ctx, const char* path, const char* filename, int in_place); +int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int in_place); /** * @brief Add file to the image. @@ -138,7 +141,7 @@ int delete_file(ccfs_handle ctx, const char* path, const char* filename, int in_ * * @return 0 on success, -1 otherwise. */ -int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, const char* file_name, +int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, uint8_t* data, size_t data_size, int in_place); /** @@ -154,7 +157,7 @@ int add_file(ccfs_handle ctx, const char* image_path, const char* file_path, con * * @return 0 on success, -1 otherwise. */ -int create_directory(ccfs_handle ctx, char* path, char* directory_name, uint8_t* file_contents, size_t file_size, int in_place); +int create_directory(ccos_disk_t* disk, char* path, char* directory_name, uint8_t* file_contents, size_t file_size, int in_place); /** * @brief Rename file in the image. @@ -170,7 +173,7 @@ int create_directory(ccfs_handle ctx, char* path, char* directory_name, uint8_t* * * @return 0 on success, -1 otherwise. */ -int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place); +int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place); /** * @brief Create new blank CCOS image file. @@ -181,6 +184,6 @@ int rename_file(ccfs_handle ctx, char* path, char* file_name, char* new_name, ui * * @return 0 on success, -1 otherwise. */ -int create_blank_image(ccfs_handle ctx, char* path, size_t size); +int create_blank_image(ccos_disk_t* disk, char* path, size_t size); #endif // WRAPPER_H From f5be764339d7ac02528cbf5c8c49a128ce9b5ef6 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Sun, 18 Jan 2026 01:16:36 +0100 Subject: [PATCH 12/13] directly use disk fields instead of passing image data and size separatly --- ccos_format.c | 2 +- ccos_image.c | 135 ++++++++++++++++++++--------------------- ccos_image.h | 135 ++++++++++++++++------------------------- ccos_private.c | 124 +++++++++++++++++++------------------ ccos_private.h | 122 +++++++++++++++---------------------- common.c | 9 +-- common.h | 7 ++- main.c | 19 +++--- wrapper.c | 162 +++++++++++++++++++++++++------------------------ wrapper.h | 98 ++++++++++++------------------ 10 files changed, 371 insertions(+), 442 deletions(-) diff --git a/ccos_format.c b/ccos_format.c index e023295..adb0c3e 100644 --- a/ccos_format.c +++ b/ccos_format.c @@ -97,7 +97,7 @@ static ccos_bitmask_list_t init_bitmask(ccos_disk_t* disk, bitmask_info_t info) } // Build list of bitmask blocks. - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, disk->data, disk->size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk); // Mark the bitmask blocks as used in the bitmask itself. for (size_t i = 0; i < info.count; i++) { diff --git a/ccos_image.c b/ccos_image.c index 78c7fd8..6bbd134 100644 --- a/ccos_image.c +++ b/ccos_image.c @@ -100,10 +100,10 @@ int ccos_set_exp_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_dat return change_date(disk, file, new_date, EXPIR); } -int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries) { +int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint16_t* entry_count, ccos_inode_t*** entries) { uint8_t* dir_contents = NULL; size_t dir_size = 0; - if (ccos_read_file(disk, dir, data, &dir_contents, &dir_size) == -1) { + if (ccos_read_file(disk, dir, &dir_contents, &dir_size) == -1) { fprintf(stderr, "Unable to get directory contents: Unable to read directory!\n"); if (dir_contents != NULL) { free(dir_contents); @@ -114,7 +114,7 @@ int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, u parsed_directory_element_t* elements = NULL; // TODO: Do we really need entry count here? *entry_count = dir->desc.dir_count; - int res = parse_directory_data(disk, data, dir_contents, dir_size, *entry_count, &elements); + int res = parse_directory_data(disk, dir_contents, dir_size, *entry_count, &elements); free(dir_contents); if (res == -1) { @@ -161,7 +161,7 @@ int ccos_is_dir(const ccos_inode_t* file) { return strncasecmp(type, CCOS_DIR_TYPE, strlen(CCOS_DIR_TYPE)) == 0; } -int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data) { +int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size) { uint32_t inode_file_size = ccos_get_file_size(file); if (inode_file_size != file_size) { fprintf(stderr, @@ -173,7 +173,7 @@ int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file size_t block_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(disk, file, image_data, &block_count, &blocks) != 0) { + if (get_file_blocks(disk, file, &block_count, &blocks) != 0) { fprintf(stderr, "Unable to write file to image: Unable to get file blocks from the block!\n"); return -1; } @@ -183,7 +183,7 @@ int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file for (size_t i = 0; i < block_count; ++i) { const uint8_t* start = NULL; size_t data_size = 0; - if (get_block_data(disk, blocks[i], image_data, &start, &data_size) != 0) { + if (get_block_data(disk, blocks[i], &start, &data_size) != 0) { fprintf(stderr, "Unable to write data: Unable to get target block address!\n"); free(blocks); return -1; @@ -198,8 +198,8 @@ int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file return 0; } -char* ccos_get_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size) { - ccos_inode_t* root = ccos_get_root_dir(disk, data, data_size); +char* ccos_get_image_label(ccos_disk_t* disk) { + ccos_inode_t* root = ccos_get_root_dir(disk); char* label = short_string_to_string((short_string_t*)&(root->desc.name_length)); if (strcmp(label, "")) { int sz = strlen(label); @@ -209,23 +209,23 @@ char* ccos_get_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size) { return label; } -int ccos_set_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size, const char* label) { +int ccos_set_image_label(ccos_disk_t* disk, const char* label) { char newlab[strlen(label) + 1]; - ccos_inode_t* root = ccos_get_root_dir(disk, data, data_size); + ccos_inode_t* root = ccos_get_root_dir(disk); if (strcmp(label, "")) { sprintf(newlab, " %s", label); - return ccos_rename_file(disk, data, data_size, root, newlab, NULL); + return ccos_rename_file(disk, root, newlab, NULL); } else { - return ccos_rename_file(disk, data, data_size, root, "", NULL); + return ccos_rename_file(disk, root, "", NULL); } } -int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count) { +int ccos_get_image_map(ccos_disk_t* disk, block_type_t** image_map, size_t* free_blocks_count) { size_t block_size = get_block_size(disk); - size_t block_count = data_size / block_size; - if (block_count * block_size != data_size) { + size_t block_count = disk->size / block_size; + if (block_count * block_size != disk->size) { fprintf(stderr, "Warn: image size (" SIZE_T " bytes) is not a multiple of a block size (" SIZE_T " bytes)\n", - data_size, block_size); + disk->size, block_size); } *image_map = (block_type_t*)calloc(block_count, sizeof(block_type_t)); @@ -237,7 +237,7 @@ int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, *free_blocks_count = 0; for (int i = 0; i < block_count; ++i) { - uint32_t block_header = *(uint32_t*)&(data[i * block_size]); + uint32_t block_header = *(uint32_t*)&disk->data[i * block_size]; block_type_t block_type = UNKNOWN; if (block_header == CCOS_EMPTY_BLOCK_MARKER) { *free_blocks_count = *free_blocks_count + 1; @@ -252,11 +252,11 @@ int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, return 0; } -int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size) { +int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t** file_data, size_t* file_size) { size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for file at 0x%x!\n", file->header.file_id); return -1; } @@ -284,7 +284,7 @@ int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_d for (int i = 0; i < blocks_count; ++i) { const uint8_t* data_start = NULL; size_t data_size = 0; - if (get_block_data(disk, blocks[i], image_data, &data_start, &data_size) == -1) { + if (get_block_data(disk, blocks[i], &data_start, &data_size) == -1) { fprintf(stderr, "Unable to get data for data block 0x%x, file at 0x%x\n", blocks[i], file->header.file_id); free(*file_data); return -1; @@ -305,19 +305,18 @@ int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_d return 0; } -int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size, - const uint8_t* file_data, size_t file_size) { +int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, size_t file_size) { size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for file id 0x%x!\n", file->header.file_id); return -1; } free(blocks); - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, image_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to write to file: invalid bitmask!\n"); return -1; @@ -336,7 +335,7 @@ int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, for (int i = 0; i < (out_blocks_count - blocks_count); ++i) { TRACE("Adding %d / %d...", i + 1, (out_blocks_count - blocks_count)); - if (add_block_to_file(disk, file, image_data, &bitmask_list) == CCOS_INVALID_BLOCK) { + if (add_block_to_file(disk, file, &bitmask_list) == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to allocate more space for the file 0x%x: no space left!\n", file->header.file_id); return -1; } @@ -347,14 +346,14 @@ int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, TRACE("Removing %d blocks from the file", blocks_count - out_blocks_count); for (int i = 0; i < (blocks_count - out_blocks_count); ++i) { TRACE("Remove %d / %d...", i + 1, (blocks_count - out_blocks_count)); - if (remove_block_from_file(disk, file, image_data, &bitmask_list) == -1) { + if (remove_block_from_file(disk, file, &bitmask_list) == -1) { fprintf(stderr, "Unable to remove block from file at 0x%x!\n", file->header.file_id); return -1; } } } - if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to get file blocks for the file id 0x%x!\n", file->header.file_id); return -1; } @@ -363,7 +362,7 @@ int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, for (int i = 0; i < blocks_count; ++i) { uint8_t* start = NULL; size_t data_size = 0; - get_block_data(disk, blocks[i], image_data, (const uint8_t**)&start, &data_size); + get_block_data(disk, blocks[i], (const uint8_t**)&start, &data_size); size_t copy_size = MIN(file_size - written, data_size); memcpy(start, &(file_data[written]), copy_size); @@ -388,27 +387,27 @@ int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, // allocate block for the new file inode; copy file inode over; write file contents to the new file; add new file to the // directory -int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, - const uint8_t* src_image, ccos_inode_t* src_file) { - ccos_bitmask_list_t dest_bitmask_list = find_bitmask_blocks(disk, dest_image, dest_image_size); +int ccos_copy_file(ccos_disk_t* src, ccos_inode_t* src_file, + ccos_disk_t* dest, ccos_inode_t* dest_directory) { + ccos_bitmask_list_t dest_bitmask_list = find_bitmask_blocks(dest); if (dest_bitmask_list.length == 0) { fprintf(stderr, "Unable to copy file: Unable to get bitmask in destination image!\n"); return -1; } uint16_t free_block = CCOS_INVALID_BLOCK; - if ((free_block = get_free_block(disk, &dest_bitmask_list)) == CCOS_INVALID_BLOCK) { + if ((free_block = get_free_block(dest, &dest_bitmask_list)) == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to copy file: no space left!\n"); return -1; } - mark_block(disk, &dest_bitmask_list, free_block, 1); - ccos_inode_t* new_file = init_inode(disk, free_block, dest_directory->header.file_id, dest_image); + mark_block(dest, &dest_bitmask_list, free_block, 1); + ccos_inode_t* new_file = init_inode(dest, free_block, dest_directory->header.file_id); uint8_t* file_data = NULL; size_t file_size = 0; TRACE("Reading file 0x%lx (%*s)", src_file->header.file_id, src_file->desc.name_length, src_file->desc.name); - if (ccos_read_file(disk, src_file, src_image, &file_data, &file_size) == -1) { + if (ccos_read_file(src, src_file, &file_data, &file_size) == -1) { fprintf(stderr, "Unable to read source file with id 0x%x!\n", src_file->header.file_id); return -1; } @@ -418,13 +417,13 @@ int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_siz offsetof(ccos_inode_t, content_inode_info) - (offsetof(ccos_inode_t, desc) + offsetof(ccos_inode_desc_t, file_size))); TRACE("Writing file 0x%lx", new_file->header.file_id); - if (ccos_write_file(disk, new_file, dest_image, dest_image_size, file_data, file_size) == -1) { + if (ccos_write_file(dest, new_file, file_data, file_size) == -1) { fprintf(stderr, "Unable to write file to file with id 0x%x!\n", free_block); free(file_data); return -1; } - int res = add_file_to_directory(disk, dest_directory, new_file, dest_image, dest_image_size); + int res = add_file_to_directory(dest, dest_directory, new_file); free(file_data); if (res == -1) { @@ -442,59 +441,59 @@ int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_siz // - Update directory checksums // - Find all file blocks; clear them and mark as free // - Clear all file content inode blocks and mark as free -int ccos_delete_file(ccos_disk_t* disk, uint8_t* image_data, size_t data_size, ccos_inode_t* file) { +int ccos_delete_file(ccos_disk_t* disk, ccos_inode_t* file) { if (ccos_is_dir(file)) { TRACE("Recursively deleting files in the directory %*s (0x%x)", file->desc.name_length, file->desc.name, file->header.file_id); uint16_t files = 0; ccos_inode_t** content = NULL; - ccos_get_dir_contents(disk, file, image_data, &files, &content); + ccos_get_dir_contents(disk, file, &files, &content); for (int c = 0; c < files; c++) { - ccos_delete_file(disk, image_data, data_size, content[c]); + ccos_delete_file(disk, content[c]); } free(content); } - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, data_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to delete file: Unable to find image bitmask!\n"); return -1; } - if (delete_file_from_parent_dir(disk, file, image_data, data_size) == -1){ + if (delete_file_from_parent_dir(disk, file) == -1){ fprintf(stderr, "Unable to delete file: Unable to delete file entry from parent dir!\n"); return -1; } size_t blocks_count = 0; uint16_t* blocks = NULL; - if (get_file_blocks(disk, file, image_data, &blocks_count, &blocks) == -1) { + if (get_file_blocks(disk, file, &blocks_count, &blocks) == -1) { fprintf(stderr, "Unable to read file blocks of file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); return -1; } for (int j = 0; j < blocks_count; ++j) { - erase_block(disk, blocks[j], image_data, &bitmask_list); + erase_block(disk, blocks[j], &bitmask_list); } free(blocks); while (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - if (remove_content_inode(disk, file, image_data, &bitmask_list) == -1) { + if (remove_content_inode(disk, file, &bitmask_list) == -1) { fprintf(stderr, "Unable to remove content block from the file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); return -1; } } - erase_block(disk, file->header.file_id, image_data, &bitmask_list); + erase_block(disk, file->header.file_id, &bitmask_list); return 0; } -ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, - uint8_t* image_data, size_t image_size) { - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, image_data, image_size); +ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, + uint8_t* file_data, size_t file_size, const char* file_name) { + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to add file: Unable to find bitmask in the image!\n"); return NULL; @@ -507,7 +506,7 @@ ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uin } mark_block(disk, &bitmask_list, free_block, 1); - ccos_inode_t* new_file = init_inode(disk, free_block, dest_directory->header.file_id, image_data); + ccos_inode_t* new_file = init_inode(disk, free_block, dest_directory->header.file_id); TRACE("Filling file info..."); new_file->desc.file_size = file_size; @@ -533,12 +532,12 @@ ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uin new_file->desc.expiration_date = (ccos_date_t){}; TRACE("Writing file 0x%lx", new_file->header.file_id); - if (ccos_write_file(disk, new_file, image_data, image_size, file_data, file_size) == -1) { + if (ccos_write_file(disk, new_file, file_data, file_size) == -1) { fprintf(stderr, "Unable to write file to file with id 0x%x!\n", new_file->header.file_id); return NULL; } - int res = add_file_to_directory(disk, dest_directory, new_file, image_data, image_size); + int res = add_file_to_directory(disk, dest_directory, new_file); if (res == -1) { fprintf(stderr, "Unable to copy file: unable to add new file with id 0x%x to the directory with id 0x%x!\n", @@ -549,15 +548,15 @@ ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uin return new_file; } -ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk, uint8_t* data, size_t data_size) { +ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk) { uint16_t superblock = 0; - if (get_superblock(disk, data, data_size, &superblock) == -1) { + if (get_superblock(disk, &superblock) == -1) { fprintf(stderr, "Unable to get root directory: unable to get superblock!\n"); return NULL; } - return get_inode(disk, superblock, data); + return get_inode(disk, superblock); } int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file) { @@ -584,9 +583,9 @@ int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file) { return 0; } -size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size) { +size_t ccos_calc_free_space(ccos_disk_t* disk) { uint16_t superblock = 0; - if (get_superblock(disk, data, data_size, &superblock) == -1) { + if (get_superblock(disk, &superblock) == -1) { fprintf(stderr, "Unable to calculate free space: Unable to get superblock!\n"); return -1; } @@ -594,13 +593,13 @@ size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size) uint16_t* free_blocks = NULL; size_t free_blocks_count = 0; - ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk, data, data_size); + ccos_bitmask_list_t bitmask_list = find_bitmask_blocks(disk); if (bitmask_list.length == 0) { fprintf(stderr, "Unable to calculate free space on the image: Unable to find bitmask!\n"); return -1; } - if (get_free_blocks(disk, &bitmask_list, data_size, &free_blocks_count, &free_blocks) == -1) { + if (get_free_blocks(disk, &bitmask_list, &free_blocks_count, &free_blocks) == -1) { fprintf(stderr, "Unable to calculate free space: Unable to get free blocks!\n"); if (free_blocks != NULL) { free(free_blocks); @@ -613,17 +612,16 @@ size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size) return free_blocks_count * get_block_size(disk); } -ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data) { +ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file) { uint16_t parent_dir_id = file->desc.dir_file_id; - return get_inode(disk, parent_dir_id, data); + return get_inode(disk, parent_dir_id); } int ccos_parse_file_name(const ccos_inode_t* inode, char* basename, char* type, size_t* name_length, size_t* type_length) { return parse_file_name((const short_string_t*)&(inode->desc.name_length), basename, type, name_length, type_length); } -ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name, - uint8_t* image_data, size_t image_size) { +ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name) { const char* dir_suffix = "~subject~"; char* filename = (char*)calloc(strlen(directory_name) + strlen(dir_suffix) + 1, sizeof(char)); @@ -635,7 +633,7 @@ ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const sprintf(filename, "%s%s", directory_name, dir_suffix); uint8_t directory_contents = CCOS_DIR_LAST_ENTRY_MARKER; - ccos_inode_t* new_directory = ccos_add_file(disk, parent_dir, &directory_contents, get_dir_default_size(disk), filename, image_data, image_size); + ccos_inode_t* new_directory = ccos_add_file(disk, parent_dir, &directory_contents, get_dir_default_size(disk), filename); free(filename); if (new_directory == NULL) { @@ -655,8 +653,7 @@ ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const return new_directory; } -int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, ccos_inode_t* file, - const char* new_name, const char* new_type) { +int ccos_rename_file(ccos_disk_t* disk, ccos_inode_t* file, const char* new_name, const char* new_type) { char name[CCOS_MAX_FILE_NAME] = {0}; char type[CCOS_MAX_FILE_NAME] = {0}; @@ -666,9 +663,9 @@ int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, return -1; } - ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file, image_data); + ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file); - if (delete_file_from_parent_dir(disk, file, image_data, image_size) == -1){ + if (delete_file_from_parent_dir(disk, file) == -1){ fprintf(stderr, "Unable to rename file: Unable to delete old file entry from parent dir!\n"); return -1; } @@ -683,7 +680,7 @@ int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, file->desc.name_length = strlen(file->desc.name); - if (add_file_to_directory(disk, parent_dir, file, image_data, image_size) == -1){ + if (add_file_to_directory(disk, parent_dir, file) == -1) { fprintf(stderr, "Unable to rename file: Unable to add new file entry from parent dir!\n"); return -1; } diff --git a/ccos_image.h b/ccos_image.h index 64a6410..18afbfc 100644 --- a/ccos_image.h +++ b/ccos_image.h @@ -1,4 +1,4 @@ -#ifndef CCOS_IMAGE_H +#ifndef CCOS_IMAGE_H #define CCOS_IMAGE_H #include "ccos_structure.h" @@ -64,26 +64,23 @@ short_string_t* ccos_get_file_name(const ccos_inode_t* file); /** * @brief Get root directory of the given image. * - * @param[in] ctx Filesystem context handle. - * @param data CCOS image data. - * @param[in] data_size Image data size. + * @param[in] disk Filesystem context handle. * * @return Root directory on success, NULL otherwise. */ -ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk, uint8_t* data, size_t data_size); +ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk); /** * @brief Read contents from the directory inode. * - * @param[in] ctx Filesystem context handle. - * @param[in] dir Directory inode. - * @param[in] data CCOS image data. - * @param entry_count Count of the items in the directory. - * @param entries Directory contents inodes. + * @param[in] disk Filesystem context handle. + * @param[in] dir Directory inode. + * @param entry_count Count of the items in the directory. + * @param entries Directory contents inodes. * * @return 0 on success, -1 otherwise. */ -int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, uint16_t* entry_count, ccos_inode_t*** entries); +int ccos_get_dir_contents(ccos_disk_t* disk, ccos_inode_t* dir, uint16_t* entry_count, ccos_inode_t*** entries); /** * @brief Determine whether the given inode is a directory's inode. @@ -166,96 +163,85 @@ int ccos_set_exp_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_dat /** * @brief Replace file in the CCOS image data. * - * @param[in] ctx Filesystem context handle. - * @param[in] file The file to replace. - * @param[in] file_data The new file contents. - * @param[in] file_size The new file size (it should match old file size). - * @param image_data CCOS image data. + * @param[in] disk Filesystem context handle. + * @param[in] file The file to replace. + * @param[in] file_data The new file contents. + * @param[in] file_size The new file size (it should match old file size). * * @return 0 on success, -1 otherwise. */ -int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size, uint8_t* image_data); +int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, uint32_t file_size); /** * @brief Get info about blocks in the image. Traverse all blocks in the CCOS image and return array filled with * corresponding block types. * - * @param[in] ctx Filesystem context handle. - * @param[in] data CCOS image data. - * @param[in] data_size The data size. + * @param[in] disk Filesystem context handle. * @param image_map Block types array. * @param free_blocks_count The free blocks count. * * @return 0 on success, -1 otherwise. */ -int ccos_get_image_map(ccos_disk_t* disk, const uint8_t* data, size_t data_size, block_type_t** image_map, size_t* free_blocks_count); +int ccos_get_image_map(ccos_disk_t* disk, block_type_t** image_map, size_t* free_blocks_count); /** * @brief Read file contents into memory buffer. * - * @param[in] ctx Filesystem context handle. - * @param[in] file File to read. - * @param[in] image_data CCOS image data. - * @param file_data The file data. - * @param file_size The file size. + * @param[in] disk Filesystem context handle. + * @param[in] file File to read. + * @param file_data The file data. + * @param file_size The file size. * * @return 0 on success, -1 otherwise. */ -int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* image_data, uint8_t** file_data, size_t* file_size); +int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t** file_data, size_t* file_size); /** * @brief Get parent directory of the given file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param file The file. - * @param data CCOS image data. * * @return Parent directory on success, NULL otherwise. */ -ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data); +ccos_inode_t* ccos_get_parent_dir(ccos_disk_t* disk, ccos_inode_t* file); /** * @brief Copy file from one CCOS image into another. * - * @param[in] ctx Filesystem context handle. - * @param dest_image The destination CCOS image. - * @param[in] dest_image_size The destination image size. - * @param dest_directory The directory in the destination image to copy file to. - * @param[in] src_image The source CCOS image. - * @param[in] src_file The source file. + * @param[in] src The source CCOS disk. + * @param[in] src_file The source file. + * @param[in] dest The destination CCOS disk. + * @param dest_directory The directory in the destination image to copy file to. * * @return 0 on success, -1 otherwise. */ -int ccos_copy_file(ccos_disk_t* disk, uint8_t* dest_image, size_t dest_image_size, ccos_inode_t* dest_directory, - const uint8_t* src_image, ccos_inode_t* src_file); +int ccos_copy_file(ccos_disk_t* src, ccos_inode_t* src_file, + ccos_disk_t* dest, ccos_inode_t* dest_directory); /** * @brief Delete file in the image. * - * @param[in] ctx Filesystem context handle. - * @param[in] image_data CCOS image data. - * @param[in] data_size The image size. - * @param[in] file The file to delete. + * @param[in] disk Filesystem context handle. + * @param[in] file The file to delete. * * @return 0 on success, -1 otherwise. */ -int ccos_delete_file(ccos_disk_t* disk, uint8_t* image_data, size_t data_size, ccos_inode_t* file); +int ccos_delete_file(ccos_disk_t* disk, ccos_inode_t* file); /** * @brief Add new file to the given directory. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param dest_directory The destination directory to add file to. * @param[in] file_data File data. * @param[in] file_size File data size. * @param[in] file_name File name. - * @param image_data CCOS image data. - * @param[in] image_size Image size. * * @return Newly created file inode on success, NULL otherwise. */ -ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, uint8_t* file_data, size_t file_size, const char* file_name, - uint8_t* image_data, size_t image_size); +ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, + uint8_t* file_data, size_t file_size, const char* file_name); /** * @brief Check file checksums and file structure, log to stderr in case of malformed file. @@ -270,28 +256,23 @@ int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file); /** * @brief Return amount of free space available in the image. * - * @param[in] ctx Filesystem context handle. - * @param data CCOS image data. - * @param[in] data_size Data size. + * @param[in] disk Filesystem context handle. * * @return Free space in the image, in bytes. */ -size_t ccos_calc_free_space(ccos_disk_t* disk, uint8_t* data, size_t data_size); +size_t ccos_calc_free_space(ccos_disk_t* disk); /** * @brief Overwrite file contents with the given data. * - * @param[in] ctx Filesystem context handle. - * @param file The file. - * @param image_data CCOS image data. - * @param[in] image_size Image data size. - * @param[in] file_data File contents. - * @param[in] file_size File contents size. + * @param[in] disk Filesystem context handle. + * @param file The file. + * @param[in] file_data File contents. + * @param[in] file_size File contents size. * * @return 0 on success, -1 otherwise. */ -int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size, - const uint8_t* file_data, size_t file_size); +int ccos_write_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file_data, size_t file_size); /** * @brief Get info about the name of the given file. @@ -309,53 +290,43 @@ int ccos_parse_file_name(const ccos_inode_t* inode, char* basename, char* type, /** * @brief Create directory in the image. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param parent_dir The parent directory. * @param[in] directory_name New directory name. - * @param image_data CCOS image data. - * @param[in] image_size CCOS image size. * * @return Newly created directory inode on success, NULL otherwise. */ -ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name, - uint8_t* image_data, size_t image_size); +ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const char* directory_name); /** * @brief Rename file and change type. * - * @param[in] ctx Filesystem context handle. - * @param image_data CCCOS image data. - * @param[in] image_size CCOS image size. - * @param file The file. - * @param[in] new_name The new name. - * @param[in] new_type The new type (optional, may be NULL, if you don't want to change it). + * @param[in] disk Filesystem context handle. + * @param file The file. + * @param[in] new_name The new name. + * @param[in] new_type The new type (optional, may be NULL, if you don't want to change it). * * @return 0 on success, -1 otherwise. */ -int ccos_rename_file(ccos_disk_t* disk, uint8_t* image_data, size_t image_size, ccos_inode_t* file, - const char* new_name, const char* new_type); +int ccos_rename_file(ccos_disk_t* disk, ccos_inode_t* file, const char* new_name, const char* new_type); /** * @brief Get label of provided image and return it. * - * @param[in] ctx Filesystem context handle. - * @param[in] data CCOS image data. - * @param[in] data_size The data size. + * @param[in] disk Filesystem context handle. * * @return Image label in char* */ -char* ccos_get_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size); +char* ccos_get_image_label(ccos_disk_t* disk); /** * @brief Set label of provided image. * - * @param[in] ctx Filesystem context handle. - * @param[in] data CCOS image data. - * @param[in] data_size The data size. - * @param[in] label The new label. + * @param[in] disk Filesystem context handle. + * @param[in] label The new label. * * @return 0 on success, -1 otherwise. */ -int ccos_set_image_label(ccos_disk_t* disk, uint8_t* data, size_t data_size, const char* label); +int ccos_set_image_label(ccos_disk_t* disk, const char* label); #endif // CCOS_IMAGE_H diff --git a/ccos_private.c b/ccos_private.c index a0b047d..8e8174a 100644 --- a/ccos_private.c +++ b/ccos_private.c @@ -82,24 +82,24 @@ void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask) { bitmask->checksum = calc_bitmask_checksum(disk, bitmask); } -ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data) { +ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block) { size_t block_size = get_block_size(disk); uint32_t addr = block * block_size; - return (ccos_inode_t*)&(data[addr]); + return (ccos_inode_t*)&disk->data[addr]; } -ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data) { +ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block) { size_t block_size = get_block_size(disk); uint32_t addr = block * block_size; - return (ccos_content_inode_t*)&(data[addr]); + return (ccos_content_inode_t*)&disk->data[addr]; } -int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, uint16_t* superblock) { - uint16_t sb = *(uint16_t*)&data[CCOS_SUPERBLOCK_ADDR_OFFSET]; +int get_superblock(ccos_disk_t* disk, uint16_t* superblock) { + uint16_t sb = *(uint16_t*)&disk->data[CCOS_SUPERBLOCK_ADDR_OFFSET]; if (sb == 0) sb = disk->superblock_fid; size_t block_size = get_block_size(disk); - uint32_t blocks_in_image = image_size / block_size; + uint32_t blocks_in_image = disk->size / block_size; if (sb > blocks_in_image) { fprintf(stderr, "Invalid superblock! (Superblock: 0x%x, but only 0x%x blocks in the image).\n", @@ -108,7 +108,7 @@ int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, ui } uint32_t block_addr = sb * block_size; - uint16_t block_header = *(uint16_t*)&data[block_addr]; + uint16_t block_header = *(uint16_t*)&disk->data[block_addr]; if (block_header != sb) { fprintf(stderr, "Invalid image: Block header 0x%x mismatches superblock 0x%x!\n", block_header, sb); return -1; @@ -119,7 +119,7 @@ int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, ui return 0; } -int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks) { +int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, size_t* blocks_count, uint16_t** blocks) { size_t inode_max_blocks = get_inode_max_blocks(disk); size_t content_inode_max_blocks = get_content_inode_max_blocks(disk); @@ -145,7 +145,7 @@ int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { TRACE("Has more than 1 block!"); - ccos_content_inode_t* content_inode = get_content_inode(disk, file->content_inode_info.block_next, data); + ccos_content_inode_t* content_inode = get_content_inode(disk, file->content_inode_info.block_next); for (;;) { TRACE("Processing extra block 0x%lx...", file->content_inode_info.block_next); @@ -193,7 +193,7 @@ int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, break; } - content_inode = get_content_inode(disk, content_inode->content_inode_info.block_next, data); + content_inode = get_content_inode(disk, content_inode->content_inode_info.block_next); } } @@ -201,14 +201,14 @@ int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, return 0; } -static ccos_bitmask_t* get_bitmask(ccos_disk_t* disk, uint8_t* data, size_t data_size) { +static ccos_bitmask_t* get_bitmask(ccos_disk_t* disk) { size_t block_size = get_block_size(disk); - uint16_t bitmask_block = *((uint16_t*)&(data[CCOS_BITMASK_ADDR_OFFSET])); + uint16_t bitmask_block = *((uint16_t*)&disk->data[CCOS_BITMASK_ADDR_OFFSET]); // FIXME: always use values from disk->bitmap_block_id. if (bitmask_block == 0 || bitmask_block == 0x5555) bitmask_block = disk->bitmap_fid; - uint32_t blocks_in_image = data_size / block_size; + uint32_t blocks_in_image = disk->size / block_size; if (bitmask_block > blocks_in_image) { fprintf(stderr, "Invalid bitmask block! (Bitmask: 0x%x, but only 0x%x blocks in the image).\n", bitmask_block, blocks_in_image); @@ -216,7 +216,7 @@ static ccos_bitmask_t* get_bitmask(ccos_disk_t* disk, uint8_t* data, size_t data } uint32_t addr = bitmask_block * block_size; - uint16_t block_header = *(uint16_t*)&(data[addr]); + uint16_t block_header = *(uint16_t*)&disk->data[addr]; if (block_header != bitmask_block) { fprintf(stderr, "Invalid image: Block header 0x%x mismatches bitmask 0x%x!\n", block_header, bitmask_block); return NULL; @@ -224,12 +224,12 @@ static ccos_bitmask_t* get_bitmask(ccos_disk_t* disk, uint8_t* data, size_t data TRACE("Bitmask: 0x%x", bitmask_block); uint32_t address = bitmask_block * block_size; - return (ccos_bitmask_t*)&(data[address]); + return (ccos_bitmask_t*)&disk->data[address]; } -ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk, uint8_t* data, size_t data_size) { +ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk) { ccos_bitmask_list_t result = {0}; - ccos_bitmask_t* first_bitmask_block = get_bitmask(disk, data, data_size); + ccos_bitmask_t* first_bitmask_block = get_bitmask(disk); if (first_bitmask_block == NULL) { fprintf(stderr, "Unable to get bitmask blocks: No bitmask in image!\n"); return result; @@ -242,7 +242,7 @@ ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk, uint8_t* data, size_t for (size_t i = 0; i < MAX_BITMASK_BLOCKS_IN_IMAGE; i++) { uint32_t offset = bitmask_addr + i * block_size; - ccos_block_header_t* header = (ccos_block_header_t*)&(data[offset]); + ccos_block_header_t* header = (ccos_block_header_t*)&disk->data[offset]; if (header->file_id == bitmask_id) { if (header->file_fragment_index != i) { fprintf(stderr, "WARN: 0x%x: Invalid bitmask fragment index: expected: " SIZE_T "; actual: %d!\n", offset, i, @@ -315,9 +315,9 @@ void mark_block(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, uint16_t b } } -ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data) { +ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block) { TRACE("Initializing inode at 0x%x!", block); - ccos_inode_t* inode = get_inode(disk, block, image_data); + ccos_inode_t* inode = get_inode(disk, block); memset(inode, 0, sizeof(ccos_inode_t)); inode->header.file_id = block; inode->desc.dir_file_id = parent_dir_block; @@ -337,9 +337,9 @@ ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_ return inode; } -ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list) { ccos_block_data_t* content_inode_info = &(file->content_inode_info); - ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file); if (last_content_inode != NULL) { content_inode_info = &(last_content_inode->content_inode_info); } @@ -352,7 +352,7 @@ ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, u mark_block(disk, bitmask_list, new_block, 1); - ccos_content_inode_t* content_inode = get_content_inode(disk, new_block, data); + ccos_content_inode_t* content_inode = get_content_inode(disk, new_block); content_inode->content_inode_info.header.file_id = content_inode_info->header.file_id; content_inode->content_inode_info.header.file_fragment_index = content_inode_info->header.file_fragment_index; @@ -372,11 +372,11 @@ ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, u return content_inode; } -ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file, const uint8_t* image_data) { +ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file) { if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - ccos_content_inode_t* result = get_content_inode(disk, file->content_inode_info.block_next, image_data); + ccos_content_inode_t* result = get_content_inode(disk, file->content_inode_info.block_next); while (result->content_inode_info.block_next != CCOS_INVALID_BLOCK) { - result = get_content_inode(disk, result->content_inode_info.block_next, image_data); + result = get_content_inode(disk, result->content_inode_info.block_next); } return result; @@ -385,15 +385,15 @@ ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode return NULL; } -void erase_block(ccos_disk_t* disk, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list) { +void erase_block(ccos_disk_t* disk, uint16_t block, ccos_bitmask_list_t* bitmask_list) { size_t block_size = get_block_size(disk); uint32_t address = block * block_size; - memset(&image[address], 0, block_size); - *(uint32_t*)&(image[address]) = CCOS_EMPTY_BLOCK_MARKER; + memset(&disk->data[address], 0, block_size); + *(uint32_t*)&disk->data[address] = CCOS_EMPTY_BLOCK_MARKER; mark_block(disk, bitmask_list, block, 0); } -int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list) { if (file->content_inode_info.block_next == CCOS_INVALID_BLOCK) { fprintf(stderr, "Unable to remove content inode: no content inodes found in file %*s (0x%x)!\n", file->desc.name_length, file->desc.name, file->header.file_id); @@ -402,9 +402,9 @@ int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, c ccos_content_inode_t* prev_inode = NULL; ccos_block_data_t* prev_block_data = &(file->content_inode_info); - ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file); - erase_block(disk, last_content_inode->content_inode_info.block_current, data, bitmask_list); + erase_block(disk, last_content_inode->content_inode_info.block_current, bitmask_list); prev_block_data->block_next = CCOS_INVALID_BLOCK; if (prev_inode != NULL) { @@ -417,9 +417,9 @@ int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, c } // remove last content block from the file -int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list) { uint16_t* content_blocks = get_inode_content_blocks(file); - ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file, data); + ccos_content_inode_t* last_content_inode = get_last_content_inode(disk, file); int content_blocks_count = get_inode_max_blocks(disk); if (last_content_inode != NULL) { content_blocks = get_content_inode_content_blocks(last_content_inode); @@ -445,12 +445,12 @@ int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, } if (last_content_block != CCOS_INVALID_BLOCK) { - erase_block(disk, last_content_block, data, bitmask_list); + erase_block(disk, last_content_block, bitmask_list); *(uint16_t*)&(content_blocks[last_content_block_index - 1]) = CCOS_INVALID_BLOCK; } if (last_content_block_index <= 1) { - if (remove_content_inode(disk, file, data, bitmask_list) == -1) { + if (remove_content_inode(disk, file, bitmask_list) == -1) { fprintf(stderr, "Unable to remove content inode after freeing block at file 0x%x!\n", file->header.file_id); return -1; } @@ -466,7 +466,7 @@ int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, } // get new block from empty blocks, modify it's header properly, reference it in the inode -uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list) { +uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list) { ccos_content_inode_t* last_content_inode = NULL; size_t block_size = get_block_size(disk); @@ -477,7 +477,7 @@ uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, int content_blocks_count = max_content_blocks; if (file->content_inode_info.block_next != CCOS_INVALID_BLOCK) { TRACE("Has content inode!"); - last_content_inode = get_last_content_inode(disk, file, data); + last_content_inode = get_last_content_inode(disk, file); content_blocks = get_content_inode_content_blocks(last_content_inode); content_blocks_count = get_content_inode_max_blocks(disk); } @@ -513,12 +513,12 @@ uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, TRACE("Last content block is 0x%x", last_content_block); uint32_t new_block_address = new_block * block_size; - ccos_block_header_t* new_block_header = (ccos_block_header_t*)&(data[new_block_address]); + ccos_block_header_t* new_block_header = (ccos_block_header_t*)&disk->data[new_block_address]; new_block_header->file_id = file->header.file_id; if (last_content_block != CCOS_INVALID_BLOCK) { uint32_t last_block_address = last_content_block * block_size; - ccos_block_header_t* last_block_header = (ccos_block_header_t*)&(data[last_block_address]); + ccos_block_header_t* last_block_header = (ccos_block_header_t*)&disk->data[last_block_address]; TRACE("Last content block of %hx is %hx with header 0x%hx 0x%hx.", file->header.file_id, last_content_block, last_block_header->file_id, last_block_header->file_fragment_index); new_block_header->file_fragment_index = last_block_header->file_fragment_index + 1; @@ -532,7 +532,7 @@ uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, TRACE("Allocating new content inode for 0x%x...", file->header.file_id); // we're run out of space for content blocks; we should allocate next content inode - ccos_content_inode_t* new_content_inode = add_content_inode(disk, file, data, bitmask_list); + ccos_content_inode_t* new_content_inode = add_content_inode(disk, file, bitmask_list); if (new_content_inode == NULL) { fprintf(stderr, "Unable to append new content inode to the file: no free space!\n"); return CCOS_INVALID_BLOCK; @@ -559,8 +559,8 @@ uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, return new_block; } -int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { - if (add_file_entry_to_dir_contents(disk, directory, image_data, image_size, file) == -1) { +int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file) { + if (add_file_entry_to_dir_contents(disk, directory, file) == -1) { fprintf(stderr, "Unable to add file with id 0x%x to directory with id 0x%x!\n", file->header.file_id, directory->header.file_id); return -1; @@ -575,7 +575,7 @@ int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode return 0; } -int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, +int parse_directory_data(ccos_disk_t* disk, const uint8_t* directory_data, size_t directory_data_size, uint16_t entry_count, parsed_directory_element_t** entries) { *entries = (parsed_directory_element_t*)calloc(entry_count, sizeof(parsed_directory_element_t)); @@ -604,7 +604,7 @@ int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, (*entries)[count].offset = offset; (*entries)[count].size = entry_size; - (*entries)[count].file = get_inode(disk, entry_block, image_data); + (*entries)[count].file = get_inode(disk, entry_block); offset += entry_size; } @@ -648,16 +648,14 @@ static int create_directory_entry(ccos_inode_t* file, int is_last, size_t* entry // find a place for the new filename in dir contents (all files are located there in alphabetical, case-insensitive // order), and insert it there -int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, - uint8_t* image_data, size_t image_size, - ccos_inode_t* file) { +int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file) { TRACE("Directory size: %d bytes, length: %d, has %d entries", directory->desc.file_size, directory->desc.dir_length, directory->desc.dir_count); uint8_t* directory_data = NULL; size_t dir_size = 0; - if (ccos_read_file(disk, directory, image_data, &directory_data, &dir_size) == -1) { + if (ccos_read_file(disk, directory, &directory_data, &dir_size) == -1) { fprintf(stderr, "Unable to get directory contents: Unable to read directory!\n"); if (directory_data != NULL) { free(directory_data); @@ -666,7 +664,7 @@ int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, } parsed_directory_element_t* elements = NULL; - if (parse_directory_data(disk, image_data, directory_data, dir_size, directory->desc.dir_count, &elements) == -1) { + if (parse_directory_data(disk, directory_data, dir_size, directory->desc.dir_count, &elements) == -1) { fprintf(stderr, "Unable to add file to directory files list: Unable to parse directory data!\n"); return -1; } @@ -749,7 +747,7 @@ int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, } // 5. Save changes - int res = ccos_write_file(disk, directory, image_data, image_size, directory_data, new_dir_size); + int res = ccos_write_file(disk, directory, directory_data, new_dir_size); free(directory_data); if (res == -1) { fprintf(stderr, "Unable to update directory contents of dir with id=0x%x!\n", directory->header.file_id); @@ -759,8 +757,8 @@ int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, return 0; } -int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size) { - ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file, image_data); +int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file) { + ccos_inode_t* parent_dir = ccos_get_parent_dir(disk, file); TRACE("Reading contents of the directory %*s (0x%x)", parent_dir->desc.name_length, parent_dir->desc.name, @@ -769,13 +767,13 @@ int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* size_t dir_size = 0; uint8_t* directory_data = NULL; - if (ccos_read_file(disk, parent_dir, image_data, &directory_data, &dir_size) == -1) { + if (ccos_read_file(disk, parent_dir, &directory_data, &dir_size) == -1) { fprintf(stderr, "Unable to read directory contents at directory id 0x%x\n", parent_dir->header.file_id); return -1; } parsed_directory_element_t* elements = NULL; - if (parse_directory_data(disk, image_data, directory_data, dir_size, parent_dir->desc.dir_count, &elements) == -1) { + if (parse_directory_data(disk, directory_data, dir_size, parent_dir->desc.dir_count, &elements) == -1) { fprintf(stderr, "Unable to add file to directory files list: Unable to parse directory data!\n"); free(directory_data); return -1; @@ -826,11 +824,11 @@ int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* size_t new_dir_size = dir_size - shrink_size; // Write dir contents back with old size to overwrite bytes at the end of dir with zeroes. - int res = ccos_write_file(disk, parent_dir, image_data, image_size, directory_data, dir_size); + int res = ccos_write_file(disk, parent_dir, directory_data, dir_size); // Do that once more with new size to clear freed up content block. if (res != -1) { - res = ccos_write_file(disk, parent_dir, image_data, image_size, directory_data, new_dir_size); + res = ccos_write_file(disk, parent_dir, directory_data, new_dir_size); } free(directory_data); @@ -923,22 +921,22 @@ int parse_file_name(const short_string_t* file_name, char* basename, char* type, return 0; } -int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size) { +int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t** start, size_t* size) { size_t block_size = get_block_size(disk); size_t log_block_size = get_log_block_size(disk); // TODO: check bounds uint32_t address = block * block_size; - *start = &(data[address + CCOS_DATA_OFFSET]); + *start = &disk->data[address + CCOS_DATA_OFFSET]; *size = log_block_size; return 0; } -int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, - uint16_t** free_blocks) { +int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, + size_t* free_blocks_count, uint16_t** free_blocks) { size_t free_count = 0; size_t block_size = get_block_size(disk); - size_t block_count = data_size / block_size; + size_t block_count = disk->size / block_size; // sanity checks int allocated_info[MAX_BITMASK_BLOCKS_IN_IMAGE]; diff --git a/ccos_private.h b/ccos_private.h index 58e2da0..4bfb2e1 100644 --- a/ccos_private.h +++ b/ccos_private.h @@ -1,4 +1,4 @@ -// +// // Created by kirill on 21.05.2020. // @@ -102,50 +102,44 @@ void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask); /** * @brief Find a superblock (i.e. the inode with the root directory description) in a CCOS filesystem image. * - * @param[in] ctx Filesystem context handle. - * @param[in] data CCOS image data. - * @param[in] image_size The image size. + * @param[in] disk Filesystem context handle. * @param superblock The superblock to return. * * @return 0 on success, with superblock numper passed out to the superblock parameter, -1 on error (i.e. in case of * invalid image format). */ -int get_superblock(ccos_disk_t* disk, const uint8_t* data, size_t image_size, uint16_t* superblock); +int get_superblock(ccos_disk_t* disk, uint16_t* superblock); /** * @brief Get the CCOS filesystem inode at the given block. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] block The block number of the inode. - * @param[in] data CCOS image data. * * @return Pointer to CCOS filesystem inode structure. */ -ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data); +ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block); /** * @brief Parse an inode and return the list of the file content blocks. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] file Inode first block number. - * @param[in] data CCOS image data. * @param blocks_count The file content blocks count. * @param blocks The file content block numbers. * * @return 0 on success, -1 otherwise. */ -int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, size_t* blocks_count, uint16_t** blocks); +int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, size_t* blocks_count, uint16_t** blocks); /** * @brief Get all bitmask blocks from the image. * - * @param[in] ctx Filesystem context handle. - * @param[in] data CCOS image data. - * @param[in] data_size Image data size. + * @param[in] disk Filesystem context handle. * * @return List of CCOS image bitmask blocks. */ -ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk, uint8_t* data, size_t data_size); +ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk); /** * @brief Find available free block in the image and return it's number. @@ -170,136 +164,119 @@ void mark_block(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, uint16_t b /** * @brief Initialize inode at the given block. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] block The block to create inode at. * @param[in] parent_dir_block The parent dir block. - * @param image_data CCOS image data. * * @return Pointer to the newly created inode on success, NULL otherwise. */ -ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block, uint8_t* image_data); +ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_block); /** * @brief Adds a new content inode (block with file block data) to the content inode list of the given file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param file The file to add content inode to. - * @param data CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. * * @return New content inode on success, NULL otherwise. */ -ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list); /** * @brief Get content inode at the given block number. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] block Block number. - * @param[in] data CCOS image data. * * @return The content inode. */ -ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block, const uint8_t* data); +ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block); /** * @brief Gets the last content inode in the content inode list of the given file. * - * @param[in] ctx Filesystem context handle. - * @param[in] file The file. - * @param[in] image_data CCOS image data. + * @param[in] disk Filesystem context handle. + * @param[in] file The file. * * @return The last content inode on success, NULL otherwise. */ -ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file, const uint8_t* image_data); +ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode_t* file); /** * @brief Cleanup image block at the given number and mark it as empty both in the image and in the image bitmask. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] block Block number. - * @param image CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. */ -void erase_block(ccos_disk_t* disk, uint16_t block, uint8_t* image, ccos_bitmask_list_t* bitmask_list); +void erase_block(ccos_disk_t* disk, uint16_t block, ccos_bitmask_list_t* bitmask_list); /** * @brief Removes the last content inode from the file's content inodes list, and erases this content inode block. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param file The file. - * @param data CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. * * @return 0 on success, -1 otherwise. */ -int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list); /** * @brief Removes last content block from the file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param file The file. - * @param data CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. * * @return 0 on success, -1 otherwise. */ -int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list); /** * @brief Adds content block to the file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param file The file. - * @param data CCOS image data. * @param bitmask_list List of CCOS image bitmask blocks. * * @return Block number of the added block on success, CCOS_INVALID_BLOCK otherwise. */ -uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* data, ccos_bitmask_list_t* bitmask_list); +uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_list_t* bitmask_list); /** * @brief Add new file entry to the list of files in the given directory. * - * @param[in] ctx Filesystem context handle. - * @param directory The directory to add file entry to. - * @param file The file to add to the directory. - * @param image_data CCOS image data. - * @param[in] image_size Image size. + * @param[in] disk Filesystem context handle. + * @param directory The directory to add file entry to. + * @param file The file to add to the directory. * * @return 0 on success, -1 otherwise. */ -int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file, uint8_t* image_data, size_t image_size); +int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file); /** * @brief Insert new directory entry into the directory, effectively making this directory a parent for the given * file. * - * @param[in] ctx Filesystem context handle. - * @param directory The directory. - * @param[in] image_data CCOS image data. - * @param[in] image_size CCOS image size. - * @param file The file. + * @param[in] disk Filesystem context handle. + * @param directory The directory. + * @param file The file. * * @return 0 on success, -1 otherwise. */ -int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, - uint8_t* image_data, size_t image_size, - ccos_inode_t* file); - +int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode_t* file); /** * @brief Delete file entry from the parent directory. * - * @param[in] ctx Filesystem context handle. - * @param file The file. - * @param[in] image_data CCOS image data. - * @param[in] image_size CCOS image size. + * @param[in] disk Filesystem context handle. + * @param file The file. * * @return 0 on success, -1 otherwise. */ -int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file, uint8_t* image_data, size_t image_size); +int delete_file_from_parent_dir(ccos_disk_t* disk, ccos_inode_t* file); /** * @brief Perse CCOS file name and return it's basename and it's type. @@ -318,16 +295,15 @@ int parse_file_name(const short_string_t* file_name, char* basename, char* type, /** * @brief Extract list of files stored in the directory by parsing directory raw contents. * - * @param[in] ctx Filesystem context handle. - * @param image_data CCOS image data. - * @param[in] directory_data Directory raw contents. - * @param[in] directory_data_size Directory contents size. - * @param[in] entry_count Number of files in the directory. - * @param entries Array of files located in the directory. + * @param[in] disk Filesystem context handle. + * @param[in] directory_data Directory raw contents. + * @param[in] directory_data_size Directory contents size. + * @param[in] entry_count Number of files in the directory. + * @param entries Array of files located in the directory. * * @return 0 on success, -1 otherwise. */ -int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, +int parse_directory_data(ccos_disk_t* disk, const uint8_t* directory_data, size_t directory_data_size, uint16_t entry_count, parsed_directory_element_t** entries); @@ -335,29 +311,27 @@ int parse_directory_data(ccos_disk_t* disk, uint8_t* image_data, * @brief Read raw data from the image at a given block. Notice it won't allocate any memory, just return a pointer * and a size of a raw data inside a block. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] block Block number. - * @param[in] data CCOS image data. * @param start Start address of the raw data. * @param size The size of a raw data. * * @return 0 on success, -1 otherwise. */ -int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t* data, const uint8_t** start, size_t* size); +int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t** start, size_t* size); /** * @brief Return info about free blocks in a CCOS image. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] bitmask_list List of CCOS image bitmask blocks. - * @param[in] data_size Image size. * @param free_blocks_count Pointer to free blocks count. * @param free_blocks Pointer to the free blocks array. * * @return 0 on success, -1 otherwise. */ -int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, size_t data_size, size_t* free_blocks_count, - uint16_t** free_blocks); +int get_free_blocks(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, + size_t* free_blocks_count, uint16_t** free_blocks) ; /** * @brief Find the index of a file in the directory data. diff --git a/common.c b/common.c index 4dc712e..28b6e04 100644 --- a/common.c +++ b/common.c @@ -4,6 +4,7 @@ #include #include #include +#include "ccos_disk.h" int (*trace)(FILE* stream, const char* format, ...) = NULL; @@ -59,7 +60,7 @@ int read_file(const char* path, uint8_t** file_data, size_t* file_size) { return 0; } -int save_image(const char* source_filename, uint8_t* data, size_t data_size, int in_place) { +int save_image(const char* source_filename, ccos_disk_t* disk, int in_place) { char* dest_filename; if (in_place) { dest_filename = (char*)source_filename; @@ -87,10 +88,10 @@ int save_image(const char* source_filename, uint8_t* data, size_t data_size, int return -1; } - size_t written = fwrite(data, sizeof(uint8_t), data_size, f); + size_t written = fwrite(disk->data, sizeof(uint8_t), disk->size, f); fclose(f); - if (written != data_size) { - fprintf(stderr, "Write size mismatch: Expected " SIZE_T ", but only " SIZE_T " written!\n", data_size, written); + if (written != disk->size) { + fprintf(stderr, "Write size mismatch: Expected " SIZE_T ", but only " SIZE_T " written!\n", disk->size, written); return -1; } diff --git a/common.h b/common.h index 678429b..79f9017 100644 --- a/common.h +++ b/common.h @@ -1,6 +1,8 @@ #ifndef COMMON_H #define COMMON_H +#include "ccos_disk.h" + #include #include @@ -51,14 +53,13 @@ int read_file(const char* path, uint8_t** file_data, size_t* file_size); * @brief Save memory buffer content to file * * @param[in] source_filename File path to save. - * @param[in] data The file data. - * @param[in] data_size The file size. + * @param[in] disk Filesystem context handle. * @param[in] in_place If true, override original target image. Otherwise, save new image under * {target_image}.out name. * * @return 0 on success, -1 otherwise. */ -int save_image(const char* source_filename, uint8_t* data, size_t data_size, int in_place); +int save_image(const char* source_filename, ccos_disk_t* disk, int in_place); const char* get_basename(const char* path); diff --git a/main.c b/main.c index edba475..fcd6939 100644 --- a/main.c +++ b/main.c @@ -246,26 +246,29 @@ int main(int argc, char** argv) { return -1; } + disk->data = file_contents; + disk->size = file_size; + int res; switch (mode) { case MODE_PRINT: { - res = print_image_info(disk, path, file_contents, file_size, short_format); + res = print_image_info(disk, path, short_format); if (res == 0) { - size_t free_bytes = ccos_calc_free_space(disk, file_contents, file_size); + size_t free_bytes = ccos_calc_free_space(disk); printf("Free space: " SIZE_T " bytes.\n", free_bytes); } break; } case MODE_DUMP: { - res = dump_image(disk, path, file_contents, file_size); + res = dump_image(disk, path); break; } case MODE_REPLACE_FILE: { - res = replace_file(disk, path, filename, target_name, file_contents, file_size, in_place); + res = replace_file(disk, path, filename, target_name, in_place); break; } case MODE_COPY_FILE: { - res = copy_file(disk, target_image, filename, file_contents, file_size, in_place); + res = copy_file(disk, target_image, filename, in_place); break; } case MODE_DELETE_FILE: { @@ -278,16 +281,16 @@ int main(int argc, char** argv) { print_usage(); res = -1; } else { - res = add_file(disk, path, filename, target_name, file_contents, file_size, in_place); + res = add_file(disk, path, filename, target_name, in_place); } break; } case MODE_CREATE_DIRECTORY: { - res = create_directory(disk, path, dir_name, file_contents, file_size, in_place); + res = create_directory(disk, path, dir_name, in_place); break; } case MODE_RENAME_FILE: { - res = rename_file(disk, path, filename, target_name, file_contents, file_size, in_place); + res = rename_file(disk, path, filename, target_name, in_place); break; } default: { diff --git a/wrapper.c b/wrapper.c index a2d113c..33f97cb 100644 --- a/wrapper.c +++ b/wrapper.c @@ -23,9 +23,9 @@ struct stat statbuf; typedef enum { RESULT_OK = 1, RESULT_ERROR, RESULT_BREAK } traverse_callback_result_t; -typedef traverse_callback_result_t (*on_file_t)(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, const char* dirname, int level, void* arg); +typedef traverse_callback_result_t (*on_file_t)(ccos_disk_t* disk, ccos_inode_t* file, const char* dirname, int level, void* arg); -typedef traverse_callback_result_t (*on_dir_t)(ccos_disk_t* disk, ccos_inode_t* dir, const uint8_t* data, const char* dirname, int level, void* arg); +typedef traverse_callback_result_t (*on_dir_t)(ccos_disk_t* disk, ccos_inode_t* dir, const char* dirname, int level, void* arg); static char* format_version(version_t* version) { char* version_string = (char*)calloc(VERSION_MAX_SIZE, sizeof(char)); @@ -37,11 +37,11 @@ static char* format_version(version_t* version) { return version_string; } -static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* data, const char* dirname, int level, +static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, const char* dirname, int level, on_file_t on_file, on_dir_t on_dir, void* arg) { uint16_t files_count = 0; ccos_inode_t** dir_contents = NULL; - if (ccos_get_dir_contents(disk, dir, data, &files_count, &dir_contents) == -1) { + if (ccos_get_dir_contents(disk, dir, &files_count, &dir_contents) == -1) { fprintf(stderr, "Unable to get root dir contents!\n"); return -1; } @@ -77,7 +77,7 @@ static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* da if (on_dir != NULL) { traverse_callback_result_t res; - if ((res = on_dir(disk, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { + if ((res = on_dir(disk, dir_contents[i], dirname, level, arg)) != RESULT_OK) { TRACE("on_dir returned %d", res); free(dir_contents); free(subdir); @@ -90,7 +90,7 @@ static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* da } } - int res = traverse_ccos_image(disk, dir_contents[i], data, subdir, level + 1, on_file, on_dir, arg); + int res = traverse_ccos_image(disk, dir_contents[i], subdir, level + 1, on_file, on_dir, arg); free(subdir); if (res == -1) { @@ -102,7 +102,7 @@ static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* da if (on_file != NULL) { traverse_callback_result_t res; - if ((res = on_file(disk, dir_contents[i], data, dirname, level, arg)) != RESULT_OK) { + if ((res = on_file(disk, dir_contents[i], dirname, level, arg)) != RESULT_OK) { TRACE("on_file returned %d", res); free(dir_contents); if (res == RESULT_ERROR) { @@ -122,8 +122,7 @@ static int traverse_ccos_image(ccos_disk_t* disk, ccos_inode_t* dir, uint8_t* da } static traverse_callback_result_t print_file_info( - ccos_disk_t* disk, ccos_inode_t* file, UNUSED const uint8_t* data, - UNUSED const char* dirname, int level, void* arg + ccos_disk_t* disk, ccos_inode_t* file, UNUSED const char* dirname, int level, void* arg ) { int short_format = *(int*)arg; uint32_t file_size = ccos_get_file_size(file); @@ -180,8 +179,8 @@ static traverse_callback_result_t print_file_info( return RESULT_OK; } -int print_image_info(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, int short_format) { - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); +int print_image_info(ccos_disk_t* disk, const char* path, int short_format) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to print image info: Unable to find root directory!\n"); return -1; @@ -218,11 +217,11 @@ int print_image_info(ccos_disk_t* disk, const char* path, uint8_t* data, size_t print_frame(128); } - return traverse_ccos_image(disk, root_dir, data, "", 0, print_file_info, print_file_info, &short_format); + return traverse_ccos_image(disk, root_dir, "", 0, print_file_info, print_file_info, &short_format); } static traverse_callback_result_t dump_dir_tree_on_file( - ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* data, const char* dirname, + ccos_disk_t* disk, ccos_inode_t* file, const char* dirname, UNUSED int level, UNUSED void* arg ) { char* abspath = (char*)calloc(sizeof(char), PATH_MAX); @@ -245,7 +244,7 @@ static traverse_callback_result_t dump_dir_tree_on_file( size_t file_size = 0; uint8_t* file_data = NULL; - if (ccos_read_file(disk, file, data, &file_data, &file_size) == -1) { + if (ccos_read_file(disk, file, &file_data, &file_size) == -1) { fprintf(stderr, "Unable to dump file at 0x%x: Unable to get file contents!\n", ccos_file_id(file)); if (file_data != NULL) { free(file_data); @@ -281,8 +280,7 @@ static traverse_callback_result_t dump_dir_tree_on_file( } static traverse_callback_result_t dump_dir_tree_on_dir( - ccos_disk_t* disk, ccos_inode_t* dir, UNUSED const uint8_t* data, - const char* dirname, UNUSED int level, UNUSED void* arg + ccos_disk_t* disk, ccos_inode_t* dir, const char* dirname, UNUSED int level, UNUSED void* arg ) { char subdir_name[CCOS_MAX_FILE_NAME]; memset(subdir_name, 0, CCOS_MAX_FILE_NAME); @@ -320,14 +318,14 @@ static traverse_callback_result_t dump_dir_tree_on_dir( return RESULT_OK; } -int dump_image(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size) { - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); +int dump_image(ccos_disk_t* disk, const char* path) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to dump image: Unable to get root directory!\n"); return -1; } - return dump_dir(disk, path, root_dir, data); + return dump_dir(disk, path, root_dir); } int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, uint8_t* image_data) { @@ -337,7 +335,7 @@ int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, ui memset(dir_type, 0, CCOS_MAX_FILE_NAME); ccos_parse_file_name(file, dir_name, dir_type, NULL, NULL); - traverse_callback_result_t res = dump_dir_tree_on_file(disk, file, image_data, path_to_dir, 0, NULL); + traverse_callback_result_t res = dump_dir_tree_on_file(disk, file, path_to_dir, 0, NULL); if (res == RESULT_ERROR) { fprintf(stderr, "Unable to dump file \"%s~%s\": %s!\n", dir_name, dir_type, strerror(errno)); @@ -347,9 +345,9 @@ int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, ui return 0; } -int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data) { +int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir) { char* name_trimmed; - if (dir == ccos_get_parent_dir(disk, dir, data)) { + if (dir == ccos_get_parent_dir(disk, dir)) { name_trimmed = strdup(short_string_to_string(ccos_get_file_name(dir))); if (strcmp(name_trimmed, "")) { int sz = strlen(name_trimmed); @@ -402,25 +400,25 @@ int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* da } } - int res = traverse_ccos_image(disk, dir, data, dirname, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); + int res = traverse_ccos_image(disk, dir, dirname, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); free(dirname); TRACE("Image dump complete!"); return res; } -int dump_image_to(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, const char* destpath) { - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); +int dump_image_to(ccos_disk_t* disk, const char* path, const char* destpath) { + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to dump image: Unable to get root directory!\n"); return -1; } - return dump_dir_to(disk, path, root_dir, data, destpath); + return dump_dir_to(disk, path, root_dir, destpath); } -int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath) { +int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, const char* destpath) { char* name_trimmed; - if (dir == ccos_get_parent_dir(disk, dir, data)) { + if (dir == ccos_get_parent_dir(disk, dir)) { name_trimmed = strdup(short_string_to_string(ccos_get_file_name(dir))); if (strcmp(name_trimmed, "")) { int sz = strlen(name_trimmed); @@ -483,15 +481,14 @@ int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* } } - int res = traverse_ccos_image(disk, dir, data, dest, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); + int res = traverse_ccos_image(disk, dir, dest, 0, dump_dir_tree_on_file, dump_dir_tree_on_dir, NULL); free(dest); TRACE("Image dump complete!"); return res; } static traverse_callback_result_t find_file_on_file( - ccos_disk_t* disk, ccos_inode_t* file, UNUSED const uint8_t* data, - UNUSED const char* dirname, UNUSED int level, void* arg + ccos_disk_t* disk, ccos_inode_t* file, UNUSED const char* dirname, UNUSED int level, void* arg ) { char* file_name = short_string_to_string(ccos_get_file_name(file)); if (file_name == NULL) { @@ -511,11 +508,11 @@ static traverse_callback_result_t find_file_on_file( return RESULT_OK; } -static int find_filename(ccos_disk_t* disk, ccos_inode_t* root_dir, uint8_t* data, const char* filename, ccos_inode_t** file, +static int find_filename(ccos_disk_t* disk, ccos_inode_t* root_dir, const char* filename, ccos_inode_t** file, int verbose) { find_file_data_t find_file_data = {.target_name = filename, .target_file = 0}; - if (traverse_ccos_image(disk, root_dir, data, "", 0, find_file_on_file, find_file_on_file, &find_file_data) == -1) { + if (traverse_ccos_image(disk, root_dir, "", 0, find_file_on_file, find_file_on_file, &find_file_data) == -1) { fprintf(stderr, "Unable to find file in image: Unable to complete search!\n"); return -1; } @@ -531,8 +528,7 @@ static int find_filename(ccos_disk_t* disk, ccos_inode_t* root_dir, uint8_t* dat return 0; } -int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, - int in_place) { +int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, int in_place) { const char* basename; if (target_name != NULL) { @@ -541,10 +537,10 @@ int replace_file(ccos_disk_t* disk, const char* path, const char* filename, cons basename = get_basename(path); } - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk); ccos_inode_t* found_file = NULL; - if (find_filename(disk, root_dir, data, basename, &found_file, 1) != 0) { + if (find_filename(disk, root_dir, basename, &found_file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", basename); return -1; } @@ -576,7 +572,7 @@ int replace_file(ccos_disk_t* disk, const char* path, const char* filename, cons return -1; } - if (ccos_replace_file(disk, found_file, file_contents, file_size, data) == -1) { + if (ccos_replace_file(disk, found_file, file_contents, file_size) == -1) { fprintf(stderr, "Unable to overwrite file %s in the image!\n", filename); free(file_contents); return -1; @@ -598,12 +594,12 @@ int replace_file(ccos_disk_t* disk, const char* path, const char* filename, cons return -1; } - size_t res = fwrite(data, sizeof(uint8_t), data_size, output); + size_t res = fwrite(disk->data, sizeof(uint8_t), disk->size, output); free(file_contents); fclose(output); - if (res != data_size) { - fprintf(stderr, "Unable to write new image: written " SIZE_T ", expected " SIZE_T ": %s!\n", res, data_size, + if (res != disk->size) { + fprintf(stderr, "Unable to write new image: written " SIZE_T ", expected " SIZE_T ": %s!\n", res, disk->size, strerror(errno)); return -1; } @@ -611,25 +607,25 @@ int replace_file(ccos_disk_t* disk, const char* path, const char* filename, cons return 0; } -static int do_copy_file(ccos_disk_t* disk, uint8_t* dest_data, size_t dest_size, ccos_inode_t* dest_root_dir, uint8_t* source_data, - ccos_inode_t* source_root_dir, const char* filename) { +static int do_copy_file(ccos_disk_t* src, ccos_inode_t* src_root_dir, const char* filename, + ccos_disk_t* dest, ccos_inode_t* dest_root_dir) { ccos_inode_t* source_file = NULL; - if (find_filename(disk, source_root_dir, source_data, filename, &source_file, 1) != 0) { + if (find_filename(src, src_root_dir, filename, &source_file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", filename); return -1; } - const ccos_inode_t* source_parent_dir = ccos_get_parent_dir(disk, source_file, source_data); + const ccos_inode_t* source_parent_dir = ccos_get_parent_dir(src, source_file); char* source_dir_name = short_string_to_string(ccos_get_file_name(source_parent_dir)); ccos_inode_t* dest_directory = NULL; - if (find_filename(disk, dest_root_dir, dest_data, source_dir_name, &dest_directory, 1) == -1) { + if (find_filename(dest, dest_root_dir, source_dir_name, &dest_directory, 1) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will copy to the " PROGRAMS_DIR_1 " instead.\n", source_dir_name); - if (find_filename(disk, dest_root_dir, dest_data, PROGRAMS_DIR_1, &dest_directory, 0) == -1 && - find_filename(disk, dest_root_dir, dest_data, PROGRAMS_DIR_2, &dest_directory, 0) == -1) { + if (find_filename(dest, dest_root_dir, PROGRAMS_DIR_1, &dest_directory, 0) == -1 && + find_filename(dest, dest_root_dir, PROGRAMS_DIR_2, &dest_directory, 0) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will copy to the root directory instead\n", PROGRAMS_DIR_1); dest_directory = dest_root_dir; @@ -638,10 +634,10 @@ static int do_copy_file(ccos_disk_t* disk, uint8_t* dest_data, size_t dest_size, free(source_dir_name); - return ccos_copy_file(disk, dest_data, dest_size, dest_directory, source_data, source_file); + return ccos_copy_file(src, source_file, dest, dest_directory); } -int copy_file(ccos_disk_t* disk, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place) { +int copy_file(ccos_disk_t* src, const char* target_image, const char* filename, int in_place) { if (target_image == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -659,33 +655,41 @@ int copy_file(ccos_disk_t* disk, const char* target_image, const char* filename, return -1; } + // TODO: Allow to copy file to disk with different properties. + ccos_disk_t dest = (ccos_disk_t) { + .sector_size = src->sector_size, + .superblock_fid = src->superblock_fid, + .bitmap_fid = src->bitmap_fid, + .data = dest_data, + .size = dest_size, + }; + ccos_inode_t* root_dir; - if ((root_dir = ccos_get_root_dir(disk, source_data, source_size)) == NULL) { + if ((root_dir = ccos_get_root_dir(src)) == NULL) { fprintf(stderr, "Unable to get root directory of the source image!\n"); - free(dest_data); + free(dest.data); return -1; } ccos_inode_t* dest_root_dir; - if ((dest_root_dir = (ccos_inode_t*)ccos_get_root_dir(disk, dest_data, dest_size)) == NULL) { + if ((dest_root_dir = ccos_get_root_dir(&dest)) == NULL) { fprintf(stderr, "Unable to get root directory of the target image!\n"); - free(dest_data); + free(dest.data); return -1; } - if (do_copy_file(disk, dest_data, dest_size, dest_root_dir, source_data, root_dir, filename) == -1) { + if (do_copy_file(src, root_dir, filename, &dest, dest_root_dir) == -1) { fprintf(stderr, "Unable to copy file \"%s\" in \"%s\"!\n", filename, target_image); - free(dest_data); + free(dest.data); return -1; } - int res = save_image(target_image, dest_data, dest_size, in_place); - free(dest_data); + int res = save_image(target_image, &dest, in_place); + free(dest.data); return res; } -int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, - uint8_t* data, size_t data_size, int in_place) { +int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, int in_place) { if (image_path == NULL) { fprintf(stderr, "No path to image is provided to copy file to!\n"); return -1; @@ -703,7 +707,7 @@ int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, c return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, data_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to add file to image: Unable to get root directory!\n"); free(file_data); @@ -712,21 +716,21 @@ int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, c ccos_inode_t* dest_dir = NULL; - if (find_filename(disk, root_dir, data, PROGRAMS_DIR_1, &dest_dir, 0) == -1 && - find_filename(disk, root_dir, data, PROGRAMS_DIR_2, &dest_dir, 0) == -1) { + if (find_filename(disk, root_dir, PROGRAMS_DIR_1, &dest_dir, 0) == -1 && + find_filename(disk, root_dir, PROGRAMS_DIR_2, &dest_dir, 0) == -1) { fprintf(stderr, "Warn: Unable to find directory %s in dest image, will add file to the root directory instead\n", PROGRAMS_DIR_1); dest_dir = root_dir; } - ccos_inode_t* new_file = ccos_add_file(disk, dest_dir, file_data, file_size, file_name, data, data_size); + ccos_inode_t* new_file = ccos_add_file(disk, dest_dir, file_data, file_size, file_name); free(file_data); if (new_file == NULL) { fprintf(stderr, "Unable to copy %s to %s!\n", file_name, file_path); return -1; } - return save_image(image_path, data, data_size, in_place); + return save_image(image_path, disk, in_place); } int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int in_place) { @@ -747,26 +751,26 @@ int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int i return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(disk, data, size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk); ccos_inode_t* file = NULL; - if (find_filename(disk, root_dir, data, filename, &file, 1) != 0) { + if (find_filename(disk, root_dir, filename, &file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", filename); free(data); return -1; } - if (ccos_delete_file(disk, data, size, file) == -1) { + if (ccos_delete_file(disk, file) == -1) { fprintf(stderr, "Unable to delete file %s!\n", filename); free(data); return -1; } - int res = save_image(path, data, size, in_place); + int res = save_image(path, disk, in_place); free(data); return res; } -int create_directory(ccos_disk_t* disk, char* path, char* directory_name, uint8_t* image_data, size_t image_size, int in_place) { +int create_directory(ccos_disk_t* disk, char* path, char* directory_name, int in_place) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -777,21 +781,21 @@ int create_directory(ccos_disk_t* disk, char* path, char* directory_name, uint8_ return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(disk, image_data, image_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to add file to image: Unable to get root directory!\n"); return -1; } - if (ccos_create_dir(disk, root_dir, directory_name, image_data, image_size) == NULL) { + if (ccos_create_dir(disk, root_dir, directory_name) == NULL) { fprintf(stderr, "Unable to create directory!\n"); return -1; } - return save_image(path, image_data, image_size, in_place); + return save_image(path, disk, in_place); } -int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place) { +int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, int in_place) { if (path == NULL) { fprintf(stderr, "No target image is provided to copy file to!\n"); return -1; @@ -807,26 +811,26 @@ int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, return -1; } - ccos_inode_t* root_dir = ccos_get_root_dir(disk, image_data, image_size); + ccos_inode_t* root_dir = ccos_get_root_dir(disk); if (root_dir == NULL) { fprintf(stderr, "Unable to rename file: Unable to get root directory!\n"); return -1; } ccos_inode_t* file = NULL; - if (find_filename(disk, root_dir, image_data, file_name, &file, 1) != 0) { + if (find_filename(disk, root_dir, file_name, &file, 1) != 0) { fprintf(stderr, "Unable to find file %s in the image!\n", file_name); return -1; } - if (ccos_rename_file(disk, image_data, image_size, file, new_name, NULL) == -1) { + if (ccos_rename_file(disk, file, new_name, NULL) == -1) { char* old_file_name = short_string_to_string(ccos_get_file_name(file)); fprintf(stderr, "Unable to rename file %s to %s!\n", old_file_name, new_name); free(old_file_name); return -1; } - int res = save_image(path, image_data, image_size, in_place); + int res = save_image(path, disk, in_place); return res; } @@ -848,7 +852,7 @@ int create_blank_image(ccos_disk_t* disk, char* path, size_t size) { return res; } - res = save_image(path, disk->data, disk->size, 1); + res = save_image(path, disk, 1); free(disk->data); return res; } diff --git a/wrapper.h b/wrapper.h index 00a8be5..d22a9c8 100644 --- a/wrapper.h +++ b/wrapper.h @@ -9,26 +9,23 @@ /** * @brief Dumps a directory recursively from CCOS disk image. * - * @param[in] ctx Filesystem context handle. - * @param[in] path The path to CCOS image. - * @param[in] dir The directory. - * @param[in] data CCOS image data. + * @param[in] disk Filesystem context handle. + * @param[in] path The path to CCOS image. + * @param[in] dir The directory. * * @return 0 on success, -1 otherwise. */ -int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data); +int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir); /** * @brief Dumps all files and directories from CCOS disk image. * - * @param[in] ctx Filesystem context handle. - * @param[in] path The path to CCOS image. - * @param[in] data CCOS image data. - * @param[in] data_size Image data size. + * @param[in] disk Filesystem context handle. + * @param[in] path The path to CCOS image. * * @return 0 on success, -1 otherwise. */ -int dump_image(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size); +int dump_image(ccos_disk_t* disk, const char* path); /** * @brief Dumps file to directory from CCOS disk image. @@ -45,82 +42,72 @@ int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, ui /** * @brief Dumps a directory recursively from CCOS disk image to a custom folder. * - * @param[in] ctx Filesystem context handle. - * @param[in] path The path to CCOS image. - * @param[in] dir The directory. - * @param[in] data CCOS image data. - * @param[in] destpath The path to destination folder. + * @param[in] disk Filesystem context handle. + * @param[in] path The path to CCOS image. + * @param[in] dir The directory. + * @param[in] destpath The path to destination folder. * * @return 0 on success, -1 otherwise. */ -int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, uint8_t* data, const char* destpath); +int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, const char* destpath); /** * @brief Dumps all files and directories from CCOS disk image to a custom folder. * - * @param[in] ctx Filesystem context handle. - * @param[in] path The path to CCOS image. - * @param[in] data CCOS image data. - * @param[in] data_size Image data size. - * @param[in] destpath The path to destination folder. + * @param[in] disk Filesystem context handle. + * @param[in] path The path to CCOS image. + * @param[in] destpath The path to destination folder. * * @return 0 on success, -1 otherwise. */ -int dump_image_to(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, const char* destpath); +int dump_image_to(ccos_disk_t* disk, const char* path, const char* destpath); /** * @brief Prints a CCOS image contents. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] path The path to CCOS image. - * @param[in] data CCOS image data. - * @param[in] data_size Image data size. * @param[in] short_format Use shorter, 80-column compatible output format. * * @return 0 on success, -1 otherwise. */ -int print_image_info(ccos_disk_t* disk, const char* path, uint8_t* data, size_t data_size, int short_format); +int print_image_info(ccos_disk_t* disk, const char* path, int short_format); /** * @brief Replace file in the CCOS image. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] path Path to the CCOS image. * @param[in] filename Path to the file to replace in the CCOS image. * @param[in] target_name If given, then the file with this name will be replaced in the CCOS image. Otherwise, * basename of the filename will be used. - * @param[in] data CCOS image data. - * @param[in] data_size CCOS image data size. * @param[in] in_place Flag indicating whether to save replaced file under a new name (path.new), or overwrite the * original file. * * @return 0 on success, -1 otherwise. */ -int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, uint8_t* data, size_t data_size, - int in_place); +int replace_file(ccos_disk_t* disk, const char* path, const char* filename, const char* target_name, int in_place); /** * @brief Copy file from one image into another. * - * @param[in] ctx Filesystem context handle. + * @param[in] src Source CCOS disk. * @param[in] target_image Path to the image to copy file to. * @param[in] filename The name of file to copy. - * @param[in] source_data CCOS source image data. - * @param[in] source_size CCOS source image data size. * @param[in] in_place If true, override original target image. Otherwise, save new image under {target_image}.out * name. * * @return 0 on success, -1 otherwise. */ -int copy_file(ccos_disk_t* disk, const char* target_image, const char* filename, uint8_t* source_data, size_t source_size, int in_place); +int copy_file(ccos_disk_t* src, const char* target_image, const char* filename, int in_place); /** * @brief Delete file in the image. * - * @param[in] ctx Filesystem context handle. - * @param[in] path Path to the image to delete file in. - * @param[in] filename The name of file to delete. - * @param[in] in_place If true, override original target image. Otherwise, save new image under {target_image}.out + * @param[in] disk Filesystem context handle. + * @param[in] path Path to the image to delete file in. + * @param[in] filename The name of file to delete. + * @param[in] in_place If true, override original target image. Otherwise, save new image under {target_image}.out * name. * * @return 0 on success, -1 otherwise. @@ -130,50 +117,43 @@ int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int i /** * @brief Add file to the image. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Filesystem context handle. * @param[in] image_path Path to the image to add file. * @param[in] file_path The path to file to add. * @param[in] file_name The name of file to add. - * @param[in] data CCOS image data. - * @param[in] data_size CCOS image data size. * @param[in] in_place If true, override original target image. Otherwise, save new image under {target_image}.out * name. * * @return 0 on success, -1 otherwise. */ -int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, - uint8_t* data, size_t data_size, int in_place); +int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, const char* file_name, int in_place); /** * @brief Create directory in the image. * - * @param[in] ctx Filesystem context handle. - * @param[in] path Path to the image to create dir. - * @param[in] directory_name The name of directory to create. - * @param[in] file_contents CCOS image data. - * @param[in] file_size CCOS image data size. - * @param[in] in_place If true, override original target image. Otherwise, save new image under + * @param[in] disk Filesystem context handle. + * @param[in] path Path to the image to create dir. + * @param[in] directory_name The name of directory to create. + * @param[in] in_place If true, override original target image. Otherwise, save new image under * {target_image}.out name. * * @return 0 on success, -1 otherwise. */ -int create_directory(ccos_disk_t* disk, char* path, char* directory_name, uint8_t* file_contents, size_t file_size, int in_place); +int create_directory(ccos_disk_t* disk, char* path, char* directory_name, int in_place); /** * @brief Rename file in the image. * - * @param[in] ctx Filesystem context handle. - * @param path Path to the image. - * @param file_name The current name of the file. - * @param new_name The new name of the file. - * @param image_data CCOS image data. - * @param[in] image_size CCOS image data size. - * @param[in] in_place If true, overwrite original target image. Otherwise, save new image under {target_image}.out + * @param[in] disk Filesystem context handle. + * @param path Path to the image. + * @param file_name The current name of the file. + * @param new_name The new name of the file. + * @param[in] in_place If true, overwrite original target image. Otherwise, save new image under {target_image}.out * name. * * @return 0 on success, -1 otherwise. */ -int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, uint8_t* image_data, size_t image_size, int in_place); +int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, int in_place); /** * @brief Create new blank CCOS image file. From 8dee095b402b3b86e55be3f98ef5ff78bf185c23 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Sun, 18 Jan 2026 17:14:43 +0100 Subject: [PATCH 13/13] fix doxygen comments --- ccos_image.h | 38 +++++++++++++++++------------------ ccos_private.h | 54 +++++++++++++++++++++++++------------------------- common.h | 2 +- wrapper.h | 24 +++++++++++----------- 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ccos_image.h b/ccos_image.h index 18afbfc..3c1b714 100644 --- a/ccos_image.h +++ b/ccos_image.h @@ -44,7 +44,7 @@ version_t ccos_get_file_version(const ccos_inode_t* file); /** * @brief Set the file version. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file The file. * @param[in] new_version The new version to set. * @@ -64,7 +64,7 @@ short_string_t* ccos_get_file_name(const ccos_inode_t* file); /** * @brief Get root directory of the given image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * * @return Root directory on success, NULL otherwise. */ @@ -73,7 +73,7 @@ ccos_inode_t* ccos_get_root_dir(ccos_disk_t* disk); /** * @brief Read contents from the directory inode. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] dir Directory inode. * @param entry_count Count of the items in the directory. * @param entries Directory contents inodes. @@ -130,7 +130,7 @@ ccos_date_t ccos_get_exp_date(const ccos_inode_t* file); /** * @brief Changes the creation date of a file or folder. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file or the directory. * @param new_date The new date variable. * @@ -141,7 +141,7 @@ int ccos_set_creation_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t ne /** * @brief Changes the modification date of a file or folder. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file or the directory. * @param new_date The new date variable. * @@ -152,7 +152,7 @@ int ccos_set_mod_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_dat /** * @brief Changes the expiration date of a file or folder. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file or the directory. * @param new_date The new date variable. * @@ -163,7 +163,7 @@ int ccos_set_exp_date(ccos_disk_t* disk, ccos_inode_t* file, ccos_date_t new_dat /** * @brief Replace file in the CCOS image data. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file The file to replace. * @param[in] file_data The new file contents. * @param[in] file_size The new file size (it should match old file size). @@ -176,7 +176,7 @@ int ccos_replace_file(ccos_disk_t* disk, ccos_inode_t* file, const uint8_t* file * @brief Get info about blocks in the image. Traverse all blocks in the CCOS image and return array filled with * corresponding block types. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param image_map Block types array. * @param free_blocks_count The free blocks count. * @@ -187,7 +187,7 @@ int ccos_get_image_map(ccos_disk_t* disk, block_type_t** image_map, size_t* free /** * @brief Read file contents into memory buffer. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file File to read. * @param file_data The file data. * @param file_size The file size. @@ -199,7 +199,7 @@ int ccos_read_file(ccos_disk_t* disk, ccos_inode_t* file, uint8_t** file_data, s /** * @brief Get parent directory of the given file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * * @return Parent directory on success, NULL otherwise. @@ -222,7 +222,7 @@ int ccos_copy_file(ccos_disk_t* src, ccos_inode_t* src_file, /** * @brief Delete file in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file The file to delete. * * @return 0 on success, -1 otherwise. @@ -232,7 +232,7 @@ int ccos_delete_file(ccos_disk_t* disk, ccos_inode_t* file); /** * @brief Add new file to the given directory. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param dest_directory The destination directory to add file to. * @param[in] file_data File data. * @param[in] file_size File data size. @@ -246,7 +246,7 @@ ccos_inode_t* ccos_add_file(ccos_disk_t* disk, ccos_inode_t* dest_directory, /** * @brief Check file checksums and file structure, log to stderr in case of malformed file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file File to check. * * @return 0 on success, -1 otherwise. @@ -256,7 +256,7 @@ int ccos_validate_file(ccos_disk_t* disk, const ccos_inode_t* file); /** * @brief Return amount of free space available in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * * @return Free space in the image, in bytes. */ @@ -265,7 +265,7 @@ size_t ccos_calc_free_space(ccos_disk_t* disk); /** * @brief Overwrite file contents with the given data. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * @param[in] file_data File contents. * @param[in] file_size File contents size. @@ -290,7 +290,7 @@ int ccos_parse_file_name(const ccos_inode_t* inode, char* basename, char* type, /** * @brief Create directory in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param parent_dir The parent directory. * @param[in] directory_name New directory name. * @@ -301,7 +301,7 @@ ccos_inode_t* ccos_create_dir(ccos_disk_t* disk, ccos_inode_t* parent_dir, const /** * @brief Rename file and change type. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * @param[in] new_name The new name. * @param[in] new_type The new type (optional, may be NULL, if you don't want to change it). @@ -313,7 +313,7 @@ int ccos_rename_file(ccos_disk_t* disk, ccos_inode_t* file, const char* new_name /** * @brief Get label of provided image and return it. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * * @return Image label in char* */ @@ -322,7 +322,7 @@ char* ccos_get_image_label(ccos_disk_t* disk); /** * @brief Set label of provided image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] label The new label. * * @return 0 on success, -1 otherwise. diff --git a/ccos_private.h b/ccos_private.h index 4bfb2e1..e3351cb 100644 --- a/ccos_private.h +++ b/ccos_private.h @@ -48,7 +48,7 @@ uint16_t calc_inode_metadata_checksum(const ccos_inode_t* inode); /** * @brief Calculates the checksum of file blocks section. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] inode The file. * * @return The file blocks section checksum. @@ -58,7 +58,7 @@ uint16_t calc_inode_blocks_checksum(ccos_disk_t* disk, const ccos_inode_t* inode /** * @brief Calculates the checksum of the content inode. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] content_inode The content inode. * * @return The content inode checksum. @@ -68,7 +68,7 @@ uint16_t calc_content_inode_checksum(ccos_disk_t* disk, const ccos_content_inode /** * @brief Calculates the checksum of image's bitmask. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] bitmask CCOS image bitmask. * * @return The bitmask checksum. @@ -78,7 +78,7 @@ uint16_t calc_bitmask_checksum(ccos_disk_t* disk, const ccos_bitmask_t* bitmask) /** * @brief Recalculate checksums of the inode. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param inode The inode. */ void update_inode_checksums(ccos_disk_t* disk, ccos_inode_t* inode); @@ -86,7 +86,7 @@ void update_inode_checksums(ccos_disk_t* disk, ccos_inode_t* inode); /** * @brief Recalculate checksum of the content inode. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param content_inode The content inode. */ void update_content_inode_checksums(ccos_disk_t* disk, ccos_content_inode_t* content_inode); @@ -94,7 +94,7 @@ void update_content_inode_checksums(ccos_disk_t* disk, ccos_content_inode_t* con /** * @brief Re-calculate and update CCOS image bitmask checksum. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param bitmask CCOS image bitmask. */ void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask); @@ -102,7 +102,7 @@ void update_bitmask_checksum(ccos_disk_t* disk, ccos_bitmask_t* bitmask); /** * @brief Find a superblock (i.e. the inode with the root directory description) in a CCOS filesystem image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param superblock The superblock to return. * * @return 0 on success, with superblock numper passed out to the superblock parameter, -1 on error (i.e. in case of @@ -113,7 +113,7 @@ int get_superblock(ccos_disk_t* disk, uint16_t* superblock); /** * @brief Get the CCOS filesystem inode at the given block. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] block The block number of the inode. * * @return Pointer to CCOS filesystem inode structure. @@ -123,7 +123,7 @@ ccos_inode_t* get_inode(ccos_disk_t* disk, uint16_t block); /** * @brief Parse an inode and return the list of the file content blocks. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file Inode first block number. * @param blocks_count The file content blocks count. * @param blocks The file content block numbers. @@ -135,7 +135,7 @@ int get_file_blocks(ccos_disk_t* disk, ccos_inode_t* file, size_t* blocks_count, /** * @brief Get all bitmask blocks from the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * * @return List of CCOS image bitmask blocks. */ @@ -144,7 +144,7 @@ ccos_bitmask_list_t find_bitmask_blocks(ccos_disk_t* disk); /** * @brief Find available free block in the image and return it's number. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] bitmask_list List of CCOS image bitmask blocks. * * @return The free block on success, CCOS_INVALID_BLOCK if no free space in the image. @@ -154,7 +154,7 @@ uint16_t get_free_block(ccos_disk_t* disk, const ccos_bitmask_list_t* bitmask_li /** * @brief Mark block in the bitmask as free or used. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param bitmask_list List of CCOS image bitmask blocks. * @param[in] block The number of the block. * @param[in] mode The mode (0 for free, 1 for used). @@ -164,7 +164,7 @@ void mark_block(ccos_disk_t* disk, ccos_bitmask_list_t* bitmask_list, uint16_t b /** * @brief Initialize inode at the given block. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] block The block to create inode at. * @param[in] parent_dir_block The parent dir block. * @@ -175,7 +175,7 @@ ccos_inode_t* init_inode(ccos_disk_t* disk, uint16_t block, uint16_t parent_dir_ /** * @brief Adds a new content inode (block with file block data) to the content inode list of the given file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file to add content inode to. * @param bitmask_list List of CCOS image bitmask blocks. * @@ -186,7 +186,7 @@ ccos_content_inode_t* add_content_inode(ccos_disk_t* disk, ccos_inode_t* file, c /** * @brief Get content inode at the given block number. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] block Block number. * * @return The content inode. @@ -196,7 +196,7 @@ ccos_content_inode_t* get_content_inode(ccos_disk_t* disk, uint16_t block); /** * @brief Gets the last content inode in the content inode list of the given file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] file The file. * * @return The last content inode on success, NULL otherwise. @@ -206,7 +206,7 @@ ccos_content_inode_t* get_last_content_inode(ccos_disk_t* disk, const ccos_inode /** * @brief Cleanup image block at the given number and mark it as empty both in the image and in the image bitmask. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] block Block number. * @param bitmask_list List of CCOS image bitmask blocks. */ @@ -215,7 +215,7 @@ void erase_block(ccos_disk_t* disk, uint16_t block, ccos_bitmask_list_t* bitmask /** * @brief Removes the last content inode from the file's content inodes list, and erases this content inode block. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * @param bitmask_list List of CCOS image bitmask blocks. * @@ -226,7 +226,7 @@ int remove_content_inode(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_lis /** * @brief Removes last content block from the file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * @param bitmask_list List of CCOS image bitmask blocks. * @@ -237,7 +237,7 @@ int remove_block_from_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_l /** * @brief Adds content block to the file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * @param bitmask_list List of CCOS image bitmask blocks. * @@ -248,7 +248,7 @@ uint16_t add_block_to_file(ccos_disk_t* disk, ccos_inode_t* file, ccos_bitmask_l /** * @brief Add new file entry to the list of files in the given directory. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param directory The directory to add file entry to. * @param file The file to add to the directory. * @@ -260,7 +260,7 @@ int add_file_to_directory(ccos_disk_t* disk, ccos_inode_t* directory, ccos_inode * @brief Insert new directory entry into the directory, effectively making this directory a parent for the given * file. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param directory The directory. * @param file The file. * @@ -271,7 +271,7 @@ int add_file_entry_to_dir_contents(ccos_disk_t* disk, ccos_inode_t* directory, c /** * @brief Delete file entry from the parent directory. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file. * * @return 0 on success, -1 otherwise. @@ -295,7 +295,7 @@ int parse_file_name(const short_string_t* file_name, char* basename, char* type, /** * @brief Extract list of files stored in the directory by parsing directory raw contents. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] directory_data Directory raw contents. * @param[in] directory_data_size Directory contents size. * @param[in] entry_count Number of files in the directory. @@ -311,7 +311,7 @@ int parse_directory_data(ccos_disk_t* disk, * @brief Read raw data from the image at a given block. Notice it won't allocate any memory, just return a pointer * and a size of a raw data inside a block. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] block Block number. * @param start Start address of the raw data. * @param size The size of a raw data. @@ -323,7 +323,7 @@ int get_block_data(ccos_disk_t* disk, uint16_t block, const uint8_t** start, siz /** * @brief Return info about free blocks in a CCOS image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] bitmask_list List of CCOS image bitmask blocks. * @param free_blocks_count Pointer to free blocks count. * @param free_blocks Pointer to the free blocks array. @@ -357,7 +357,7 @@ int is_root_dir(const ccos_inode_t* file); /** * @brief Changes the date of a file or folder. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param file The file or the directory. * @param new_date The new date variable. * @param type Date type to replace (CREATED - creation, MODIF - modification, EXPIR - expiration). diff --git a/common.h b/common.h index 79f9017..e624662 100644 --- a/common.h +++ b/common.h @@ -53,7 +53,7 @@ int read_file(const char* path, uint8_t** file_data, size_t* file_size); * @brief Save memory buffer content to file * * @param[in] source_filename File path to save. - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] in_place If true, override original target image. Otherwise, save new image under * {target_image}.out name. * diff --git a/wrapper.h b/wrapper.h index d22a9c8..03b99c5 100644 --- a/wrapper.h +++ b/wrapper.h @@ -9,7 +9,7 @@ /** * @brief Dumps a directory recursively from CCOS disk image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path The path to CCOS image. * @param[in] dir The directory. * @@ -20,7 +20,7 @@ int dump_dir(ccos_disk_t* disk, const char* path, ccos_inode_t* dir); /** * @brief Dumps all files and directories from CCOS disk image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path The path to CCOS image. * * @return 0 on success, -1 otherwise. @@ -30,7 +30,7 @@ int dump_image(ccos_disk_t* disk, const char* path); /** * @brief Dumps file to directory from CCOS disk image. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path_to_dir The path to destination directory. * @param[in] file The file to dump. * @param[in] image_data CCOS image data. @@ -42,7 +42,7 @@ int dump_file(ccos_disk_t* disk, const char* path_to_dir, ccos_inode_t* file, ui /** * @brief Dumps a directory recursively from CCOS disk image to a custom folder. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path The path to CCOS image. * @param[in] dir The directory. * @param[in] destpath The path to destination folder. @@ -54,7 +54,7 @@ int dump_dir_to(ccos_disk_t* disk, const char* path, ccos_inode_t* dir, const ch /** * @brief Dumps all files and directories from CCOS disk image to a custom folder. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path The path to CCOS image. * @param[in] destpath The path to destination folder. * @@ -65,7 +65,7 @@ int dump_image_to(ccos_disk_t* disk, const char* path, const char* destpath); /** * @brief Prints a CCOS image contents. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path The path to CCOS image. * @param[in] short_format Use shorter, 80-column compatible output format. * @@ -76,7 +76,7 @@ int print_image_info(ccos_disk_t* disk, const char* path, int short_format); /** * @brief Replace file in the CCOS image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path Path to the CCOS image. * @param[in] filename Path to the file to replace in the CCOS image. * @param[in] target_name If given, then the file with this name will be replaced in the CCOS image. Otherwise, @@ -104,7 +104,7 @@ int copy_file(ccos_disk_t* src, const char* target_image, const char* filename, /** * @brief Delete file in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path Path to the image to delete file in. * @param[in] filename The name of file to delete. * @param[in] in_place If true, override original target image. Otherwise, save new image under {target_image}.out @@ -117,7 +117,7 @@ int delete_file(ccos_disk_t* disk, const char* path, const char* filename, int i /** * @brief Add file to the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] image_path Path to the image to add file. * @param[in] file_path The path to file to add. * @param[in] file_name The name of file to add. @@ -131,7 +131,7 @@ int add_file(ccos_disk_t* disk, const char* image_path, const char* file_path, c /** * @brief Create directory in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path Path to the image to create dir. * @param[in] directory_name The name of directory to create. * @param[in] in_place If true, override original target image. Otherwise, save new image under @@ -144,7 +144,7 @@ int create_directory(ccos_disk_t* disk, char* path, char* directory_name, int in /** * @brief Rename file in the image. * - * @param[in] disk Filesystem context handle. + * @param[in] disk Compass disk image. * @param path Path to the image. * @param file_name The current name of the file. * @param new_name The new name of the file. @@ -158,7 +158,7 @@ int rename_file(ccos_disk_t* disk, char* path, char* file_name, char* new_name, /** * @brief Create new blank CCOS image file. * - * @param[in] ctx Filesystem context handle. + * @param[in] disk Compass disk image. * @param[in] path Path where to create the new image file. * @param[in] size Size of the image in bytes. Must be a multiple of the sector size. *