From b31439bcb6e986e77f107e9e5b95c38183f535a4 Mon Sep 17 00:00:00 2001 From: Godzil Date: Thu, 26 May 2022 12:02:47 +0100 Subject: [PATCH] Now we can generate a fairly basic FS. Added some test material --- CMakeLists.txt | 22 ++++---- includes/miniffs.h | 41 ++++++++------ includes/platform/file.h | 47 +++++++++++++--- includes/platform/memory.h | 16 ++++-- mffs.c | 16 ++++-- miniffs.c | 14 +++++ miniffs_tools.c | 107 ++++++++++++++++++++++++++++++++++++- platform/file.c | 58 ++++++++++++++++++++ platform/memory.c | 3 ++ test/hello.txt | 1 + test/test_image.json | 11 ++++ 11 files changed, 296 insertions(+), 40 deletions(-) create mode 100644 test/hello.txt create mode 100644 test/test_image.json diff --git a/CMakeLists.txt b/CMakeLists.txt index e835b62..de8ee15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,15 +10,8 @@ include(GetGitRevisionDescription) git_describe(VERSION --tags --dirty=-dirty) #parse the version information into pieces. -string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") -string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") -string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_MICRO "${VERSION}") -string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+-(.*)" "\\1" VERSION_SHA1 "${VERSION}") message("-- Building version ${VERSION}") -add_compile_options(-DV_MAJOR=${VERSION_MAJOR}) -add_compile_options(-DV_MINOR=${VERSION_MINOR}) -add_compile_options(-DV_MICRO=${VERSION_MICRO}) -add_compile_options(-DV_TEXT="${VERSION_SHA1}") +ADD_COMPILE_DEFINITIONS(VERSION="${VERSION}") set(VALID_BUILD_PLATFORM MEMORY FILE) @@ -31,11 +24,18 @@ string(TOLOWER ${BUILD_PLATFORM} PLATFORM_FILE) add_library(miniffs) target_sources(miniffs PRIVATE platform/${PLATFORM_FILE}.c miniffs.c) -target_include_directories(miniffs PUBLIC includes/) +target_include_directories(miniffs PRIVATE includes/) +target_compile_definitions(miniffs PRIVATE BUILD_PLATFORM_${BUILD_PLATFORM}) if (BUILD_HOST_TOOLS) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + add_subdirectory(external/cJSON) + # Offline tools use the file backend so we have to include the lib by hand. add_executable(mffs) - target_sources(mffs PRIVATE platform/file.c miniffs.c mffs.c) - target_include_directories(mffs PRIVATE includes/) + target_sources(mffs PRIVATE platform/file.c miniffs.c miniffs_tools.c mffs.c) + target_link_libraries(mffs ${CJSON_LIB}) + target_include_directories(mffs PRIVATE includes/ external/) + target_compile_definitions(mffs PRIVATE BUILD_PLATFORM_FILE) + target_compile_definitions(mffs PRIVATE BUILD_HOST_TOOLS) endif() diff --git a/includes/miniffs.h b/includes/miniffs.h index 1cbce75..2ed6003 100644 --- a/includes/miniffs.h +++ b/includes/miniffs.h @@ -11,14 +11,6 @@ #include -#if BUILD_TARGET == MEMORY -#include -#elif BUILD_TARGET == FILE -#include -#else -#error Unknown build target -#endif - /* * The pack(1) may not be needed, but better be safe than sorry to * have a consistent binary representation across architectures @@ -38,21 +30,29 @@ typedef struct miniffs_header_t uint32_t entry_count; fileentry_t fent[]; } miniffs_header_t; - #pragma pack() -typedef struct miniffs_t miniffs_t; +#if BUILD_PLATFORM_MEMORY +#include +#elif BUILD_PLATFORM_FILE +#include +#else +#error Unknown build target. +#endif /* Somewhat similar structure to the plain C FILE structure */ typedef struct file_t { void *private; - fileentry_t fent; /***< file linked to this structure */ + fileentry_t *fent; /***< file linked to this structure */ uint32_t offset; /***< current position in the file */ } file_t; -#define MAKE4(_a, _b, _c, _d) ((_a & 0xFF) << 21) | ((_b & 0xFF) << 16) | ((_c & 0xFF) << 8) | (_d & 0xFF) - +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define MAKE4(_a, _b, _c, _d) (((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF) +#else +#define MAKE4(_d, _c, _b, _a) (((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF) +#endif #define MINIFFS_MAGIC MAKE4('M', 'F', 'F', 'S') enum { @@ -65,8 +65,8 @@ enum { * Public functions used reading the filesystem * This implementation is system dependant as it relly on how the memory is architectured and where the MiniFFS is stored. */ -miniffs_t *miniffs_openfs(void *address); /***< Open a MiniFFS filesystem */ +/* miniffs_openfs is backend specific and will be found in the backend header file */ file_t *miniffs_open(miniffs_t *fs, char *filename); /***< Open a file */ int miniffs_close(file_t *file); /***< Close a file */ void *miniffs_map(file_t *file); /***< Map a file to memory */ @@ -84,7 +84,7 @@ typedef enum miniffs_error_t miniffs_error_t miniffs_geterror(); /***< Return last error */ -#ifdef BUILDING_HOST_TOOLS +#ifdef BUILD_HOST_TOOLS /* * Functions used for offline creation of the filesystem */ @@ -93,6 +93,15 @@ int miniffs_addfile(miniffs_t *fs, char *name, char *ext, char *host_path); int miniffs_delfile(miniffs_t *fs, char *name, char *ext, char *host_path); int miniffs_writeimage(miniffs_t *fs, char *host_path); int miniffs_closefs(miniffs_t *fs); -#endif /* BUILDING_HOST_TOOLS */ +#endif /* BUILD_HOST_TOOLS */ + +#ifdef __miniffs_internal +/* + * Function that are private to the library + */ +int miniffs_checkfs(miniffs_t *fs); +fileentry_t *miniffs_findfile(miniffs_t *fs, char *filename); + +#endif /* __miniffs_internal */ #endif /* MINIFFS_H */ diff --git a/includes/platform/file.h b/includes/platform/file.h index d4fb2bc..f512a3c 100644 --- a/includes/platform/file.h +++ b/includes/platform/file.h @@ -1,8 +1,43 @@ -// -// Created by Manoel.Trapier on 25/05/2022. -// +/****************************************************************************** + * MiniFFS : Mini Flat File System + * platform/file.h: Specific functions for the File backend + * + * Copyright (c) 2008-2022 986-Studio. All rights reserved. + * + ******************************************************************************/ -#ifndef MINIFFS_FILE_H -#define MINIFFS_FILE_H +#ifndef MINIFFS_PLATFORM_FILE_H +#define MINIFFS_PLATFORM_FILE_H -#endif //MINIFFS_FILE_H +#include +#include + +#ifdef BUILD_HOST_TOOLS +typedef struct fs_fent_t +{ + char name[8]; + char ext[3]; + bool deleted; + bool mapped; + uint32_t size; + char *file_pointer; +} fs_fent_t; +#endif + +typedef struct miniffs_t +{ + miniffs_header_t *header; +#ifdef BUILD_HOST_TOOLS + uint32_t file_count; /***< Number of valid files in the list */ + uint32_t file_list_count; /***< Number of items in the list */ + uint32_t file_list_size; /***< Size of the list */ + fs_fent_t *files; /***< File entry list */ +#endif +} miniffs_t; + +size_t host_map_file(char *filename, char **dest); +void host_unmap_file(char **dest, size_t length); + +miniffs_t *miniffs_openfs(char *host_file); /***< Open a MiniFFS filesystem */ + +#endif /* MINIFFS_PLATFORM_FILE_H */ diff --git a/includes/platform/memory.h b/includes/platform/memory.h index 8cebf86..fdc0d9b 100644 --- a/includes/platform/memory.h +++ b/includes/platform/memory.h @@ -1,8 +1,18 @@ -// -// Created by Manoel.Trapier on 25/05/2022. -// +/****************************************************************************** + * MiniFFS : Mini Flat File System + * platform/memory.h: Specific functions for the Memory backend + * + * Copyright (c) 2008-2022 986-Studio. All rights reserved. + * + ******************************************************************************/ #ifndef MINIFFS_PLATFORM_MEMORY_H #define MINIFFS_PLATFORM_MEMORY_H +typedef struct miniffs_t +{ + miniffs_header_t *header; + void *memoryOffset; +} miniffs_t; + #endif /* MINIFFS_PLATFORM_MEMORY_H */ diff --git a/mffs.c b/mffs.c index 16b56e4..92b83b9 100644 --- a/mffs.c +++ b/mffs.c @@ -1,11 +1,21 @@ #include #include -#include +#include +#include +int main(int argc, char *argv[]) +{ + miniffs_t *fs; + + printf("mffs version %s\n", VERSION); + + fs = miniffs_createfs(); + miniffs_addfile(fs, "HELLO", "TXT", "test/hello.txt"); + + miniffs_writeimage(fs, "test/output.mffs"); + miniffs_closefs(fs); -int main() { - printf("Hello, World!\n"); return 0; } diff --git a/miniffs.c b/miniffs.c index 7f10fc0..8dbac4f 100644 --- a/miniffs.c +++ b/miniffs.c @@ -5,3 +5,17 @@ * Copyright (c) 2008-2022 986-Studio. All rights reserved. * ******************************************************************************/ + +#define __miniffs_internal +#include + +int miniffs_checkfs(miniffs_t *fs) +{ + return 0; +} + +fileentry_t *miniffs_findfile(miniffs_t *fs, char *filename) +{ + + return NULL; +} \ No newline at end of file diff --git a/miniffs_tools.c b/miniffs_tools.c index a3e24ff..34cbe5f 100644 --- a/miniffs_tools.c +++ b/miniffs_tools.c @@ -1,8 +1,113 @@ /****************************************************************************** * MiniFFS : Mini Flat File System - * miniffs_tools.c: Contain all the funciton needed for offline tools + * miniffs_tools.c: Contain all the function needed for offline tools * * Copyright (c) 2008-2022 986-Studio. All rights reserved. * ******************************************************************************/ +#include +#include +#include +#ifdef _WIN32 +#include +#endif + +#include + +miniffs_t *miniffs_createfs() +{ + miniffs_t *fs = (miniffs_t *)calloc(1, sizeof(miniffs_t)); + + fs->file_list_size = 2; + fs->files = (fs_fent_t *)calloc(2, sizeof(fs_fent_t)); + + return fs; +} + +int miniffs_addfile(miniffs_t *fs, char *name, char *ext, char *host_path) +{ + fs_fent_t *cur; + uint8_t nameLen = strnlen(name, 8); + uint8_t extLen = strnlen(ext, 3); + + if (fs->file_list_count == fs->file_list_size) + { + fs->file_list_size *= 2; + fs->files = realloc(fs->files, sizeof(fs_fent_t) * fs->file_list_size); + } + + cur = &fs->files[fs->file_list_count]; + memset(cur, 0, sizeof(fs_fent_t)); + memcpy(cur->name, name, nameLen); + memcpy(cur->ext, ext, extLen); + + cur->size = host_map_file(host_path, &cur->file_pointer); + + cur->deleted = false; + + fs->file_list_count++; + fs->file_count++; +} + +int miniffs_delfile(miniffs_t *fs, char *name, char *ext, char *host_path) +{ + // TODO: + // 1 - find file + // 2 - mark as deleted +} + +int miniffs_writeimage(miniffs_t *fs, char *host_path) +{ + int i; + FILE *fp; + miniffs_header_t *header; + size_t headerSize = sizeof(miniffs_header_t) + fs->file_count * sizeof(fileentry_t); + size_t fileIndex = 0; + size_t filePosition = headerSize; + + header = (miniffs_header_t *)calloc(1, headerSize); + + header->magic = MINIFFS_MAGIC; + header->entry_count = fs->file_count; + + for(i = 0; i < fs->file_list_count; i++) + { + if (fs->files[i].deleted == false) + { + memcpy(header->fent[fileIndex].name, fs->files[i].name, 8); + memcpy(header->fent[fileIndex].ext, fs->files[i].ext, 3); + header->fent[fileIndex].size = fs->files[i].size; + header->fent[fileIndex].offset = filePosition; + fileIndex ++; + filePosition += header->fent[fileIndex].size; + } + } + + fp = fopen(host_path, "wb"); + + fwrite(header, 1, headerSize, fp); + for(i = 0; i < fs->file_count; i++) + { + if (fs->files[i].deleted == false) + { + fwrite(fs->files[i].file_pointer, 1, fs->files[i].size, fp); + } + } + fclose(fp); +} + +int miniffs_closefs(miniffs_t *fs) +{ + int i; + for(i = 0; i < fs->file_count; i++) + { + if (fs->files[i].mapped) + { + host_unmap_file(&fs->files[i].file_pointer, fs->files[i].size); + fs->files[i].mapped = false; + } + } + free(fs->files); + free(fs); +} diff --git a/platform/file.c b/platform/file.c index eb05145..6d7db04 100644 --- a/platform/file.c +++ b/platform/file.c @@ -5,3 +5,61 @@ * Copyright (c) 2008-2022 986-Studio. All rights reserved. * ******************************************************************************/ +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#endif + +#define __miniffs_internal +#include + +size_t host_map_file(char *filename, char **dest) +{ + char *ret_ptr; + size_t fileSize; +#ifdef _WIN32 + /* As windows do not provide an easy to use mmap equivalent, let's use the fallback + * of opening the file, allocating memory and read the file in the said memory + */ + FILE *fp; + fp = fopen(filename, "rb"); + fseek(fp, 0, SEEK_END); + fileSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + ret_ptr = (char *)calloc(1, fileSize); + fread(ret_ptr, 1, fileSize, fp); + fclose(fp); +#else + int fd; + struct stat FileStat; + + fd = open(filename, O_RDWR); + fstat(fd, &FileStat); + ret_ptr = (char *)mmap(NULL, FileStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + close(fd); + fileSize = FileStat.st_size + if (ret_ptr == MAP_FAILED) + { + ret_ptr = NULL; + } +#endif + *dest = ret_ptr; + return fileSize; +} + +void host_unmap_file(char **dest, size_t length) +{ +#ifdef _WIN32 + /* As for windows we don't mmap, let's just free! */ + free(*dest); +#else + munmap(*dest, length); +#endif + + *dest = NULL; +} \ No newline at end of file diff --git a/platform/memory.c b/platform/memory.c index 4c86a79..ed3476d 100644 --- a/platform/memory.c +++ b/platform/memory.c @@ -5,3 +5,6 @@ * Copyright (c) 2008-2022 986-Studio. All rights reserved. * ******************************************************************************/ + +#define __miniffs_internal +#include \ No newline at end of file diff --git a/test/hello.txt b/test/hello.txt new file mode 100644 index 0000000..c57eff5 --- /dev/null +++ b/test/hello.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/test/test_image.json b/test/test_image.json new file mode 100644 index 0000000..fa14777 --- /dev/null +++ b/test/test_image.json @@ -0,0 +1,11 @@ +{ + "files": + [ + { + "name": "HELLO", + "ext": "TXT", + "file": "hello.txt" + } + ], + "output": "test.mffs" +} \ No newline at end of file