From 3780b4844c170a0e8f5f3b1fa615f0732009bbd8 Mon Sep 17 00:00:00 2001 From: Lucjan Bryndza Date: Mon, 28 Dec 2020 14:27:58 +0100 Subject: [PATCH] [EGD-5074] Add native fscore for emulator This is a first commit when the emulator uses the new filesystem core. libiosyscall library read environment variable IOSYSCALS_REDIRECT_TO_IMAGE When IOSYSCALS_REDIRECT_TO_IMAGE=1 all syscalls are redirected to the image. If env is not defined or set to 0 only paths are translated and redirected to the native linux syscalls [EGD-5074] Remove free rtox library Remove unneeded fat library from the freertos [EGD-5074] Fix freertos mutex as unique Add freertos mutex in the unique_ptr for avoid inclusion of the freertos.h [EGD-5074] Remove frertos-fat submodule Remove uneeded fat freertos submodule [EGD-5074] Add handle types in the vfs_subsystem Add handle types in the vfs subsystem [EGD-5074] Add submodule for hashmap Add submodule for hashmap [EGD-5074] Add support for dirent Add support for dirent for new filesystem [EGD-5074] Fix mutex class Remove mutex in header [EGD-5074] Remove old vfs from file indexer File indexer should be fixed for use new vfs [EGD-5074] Fix unit test vfs Remove unit tests vfs for clas [EGD-5074] Add Posix implementation with new fs Add posix implementation with new fs core [EGD-5074] Fix stdio syscalls Fix all stdio syscalls [EGD-5074] Fix iosyscalls scan family Fix iosyscalls scan family [EGD-5074] Fix native API Fix native api Work in progress some minor fixes [EGD-5074] Fix lib stdio Fix lib stdio [EGD-5074] fix lseek return value in fat driver Fix lseek return value in the fat driver [EGD-5074] Unit test fix Unittest fixes [EGD-5074] Emulator syscalls Signed-off-by: Lucjan Bryndza --- .gitmodules | 6 +- board/linux/libiosyscalls/CMakeLists.txt | 19 +- board/linux/libiosyscalls/include/debug.hpp | 18 +- .../libiosyscalls/include/dirent_support.hpp | 19 - .../linux/libiosyscalls/include/internal.hpp | 17 - .../libiosyscalls/include/iosyscalls.hpp | 45 ++ board/linux/libiosyscalls/src/dirent.cpp | 308 +++++---- .../libiosyscalls/src/dirent_support.cpp | 93 --- board/linux/libiosyscalls/src/iosyscalls.cpp | 164 +++++ .../libiosyscalls/src/syscalls_posix.cpp | 433 +++++++------ .../src/syscalls_scan_family.cpp | 81 +-- .../libiosyscalls/src/syscalls_stdio.cpp | 609 ++++++++++-------- .../ServiceFileIndexer.cpp | 4 + .../service-fileindexer/StartupIndexer.cpp | 4 +- module-utils/parallel-hashmap | 1 + module-utils/test/unittest_utils.cpp | 2 +- module-vfs/CMakeLists.txt | 49 +- .../include/ff_eMMC_user_disk.hpp | 16 - .../free_rtos_custom/portable/common.cpp | 28 - .../portable/ff_eMMC_user_disk.cpp | 385 ----------- .../cross/free_rtos_custom/portable/vfs.cpp | 52 -- module-vfs/board/freeRTOS_FAT | 1 - .../include/FreeRTOSFATConfig.h | 322 --------- .../include/ff_image_user_disk.hpp | 14 - .../free_rtos_custom/portable/common.cpp | 12 - .../portable/ff_image_user_disk.cpp | 426 ------------ .../linux/free_rtos_custom/portable/vfs.cpp | 80 --- .../drivers/include/thirdparty/fatfs/ffconf.h | 2 +- .../drivers/src/purefs/fs/filesystem_vfat.cpp | 7 +- .../include/ff_stdio_listdir_recursive.h | 24 - .../freertos-fat-custom/src/ff_file_flush.c | 100 --- .../freertos-fat-custom/src/ff_file_flush.h | 7 - .../freertos-fat-custom/src/ff_stdio_flush.c | 52 -- .../src/ff_stdio_listdir_recursive.c | 121 ---- module-vfs/include/user/deprecated/vfs.hpp | 11 +- .../include/user/deprecated/vfsNotifier.hpp | 2 +- .../user/purefs/blkdev/disk_manager.hpp | 11 +- .../include/user/purefs/fs/filesystem.hpp | 11 +- .../include/user/purefs/vfs_subsystem.hpp | 3 +- module-vfs/src/deprecated/vfs.cpp | 378 ++--------- module-vfs/src/purefs/blkdev/disk_manager.cpp | 14 +- module-vfs/src/purefs/fs/filesystem.cpp | 25 +- module-vfs/targets/Target_Cross.cmake | 9 - module-vfs/targets/Target_Linux.cmake | 4 - module-vfs/tests/CMakeLists.txt | 10 - module-vfs/tests/unittest_filesystem_core.cpp | 2 +- module-vfs/tests/unittest_vfs.cpp | 171 ----- source/main.cpp | 14 +- 48 files changed, 1167 insertions(+), 3019 deletions(-) delete mode 100644 board/linux/libiosyscalls/include/dirent_support.hpp delete mode 100644 board/linux/libiosyscalls/include/internal.hpp create mode 100644 board/linux/libiosyscalls/include/iosyscalls.hpp delete mode 100644 board/linux/libiosyscalls/src/dirent_support.cpp create mode 100644 board/linux/libiosyscalls/src/iosyscalls.cpp create mode 160000 module-utils/parallel-hashmap delete mode 100644 module-vfs/board/cross/free_rtos_custom/include/ff_eMMC_user_disk.hpp delete mode 100644 module-vfs/board/cross/free_rtos_custom/portable/common.cpp delete mode 100644 module-vfs/board/cross/free_rtos_custom/portable/ff_eMMC_user_disk.cpp delete mode 100644 module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp delete mode 160000 module-vfs/board/freeRTOS_FAT delete mode 100644 module-vfs/board/free_rtos_custom/include/FreeRTOSFATConfig.h delete mode 100644 module-vfs/board/linux/free_rtos_custom/include/ff_image_user_disk.hpp delete mode 100644 module-vfs/board/linux/free_rtos_custom/portable/common.cpp delete mode 100644 module-vfs/board/linux/free_rtos_custom/portable/ff_image_user_disk.cpp delete mode 100644 module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp delete mode 100644 module-vfs/freertos-fat-custom/include/ff_stdio_listdir_recursive.h delete mode 100644 module-vfs/freertos-fat-custom/src/ff_file_flush.c delete mode 100644 module-vfs/freertos-fat-custom/src/ff_file_flush.h delete mode 100644 module-vfs/freertos-fat-custom/src/ff_stdio_flush.c delete mode 100644 module-vfs/freertos-fat-custom/src/ff_stdio_listdir_recursive.c delete mode 100644 module-vfs/targets/Target_Cross.cmake delete mode 100644 module-vfs/tests/unittest_vfs.cpp diff --git a/.gitmodules b/.gitmodules index e93d4606f07c27ed5c111ee0c075ceab0e4f11dd..8ac3d4a6d27991b581698639635d7b038fdba893 100644 --- a/.gitmodules +++ b/.gitmodules @@ -53,9 +53,6 @@ [submodule "module-utils/magic_enum"] path = module-utils/magic_enum url = git@github.com:Neargye/magic_enum.git -[submodule "module-vfs/board/freeRTOS_FAT"] - path = module-vfs/board/freeRTOS_FAT - url = ../Lab-Project-FreeRTOS-FAT.git [submodule "module-utils/tinyexpr"] path = module-utils/tinyexpr url = https://github.com/codeplea/tinyexpr.git @@ -71,3 +68,6 @@ [submodule "module-vfs/thirdparty/lfsfs/littlefs"] path = module-vfs/thirdparty/lfsfs/littlefs url = https://github.com/littlefs-project/littlefs.git +[submodule "module-utils/parallel-hashmap"] + path = module-utils/parallel-hashmap + url = https://github.com/greg7mdp/parallel-hashmap.git diff --git a/board/linux/libiosyscalls/CMakeLists.txt b/board/linux/libiosyscalls/CMakeLists.txt index 3582ee994e339f7e079380fa95731a8ace035ba7..65b6e5b62c95e8f1d9d2699d6b8302f98e6ee805 100644 --- a/board/linux/libiosyscalls/CMakeLists.txt +++ b/board/linux/libiosyscalls/CMakeLists.txt @@ -5,26 +5,29 @@ project(iosyscalls VERSION 1.0 set(SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dirent_support.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dirent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/iosyscalls.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dirent.cpp ) + set(INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_SOURCE_DIR}/module-vfs/board/freeRTOS_FAT/include" - "${CMAKE_SOURCE_DIR}/module-os/FreeRTOS/include" "${CMAKE_SOURCE_DIR}/module-os/board/linux" - "${CMAKE_SOURCE_DIR}/module-vfs/board/free_rtos_custom/include" + "${CMAKE_SOURCE_DIR}/module-os/RTOSWrapper/include" + "${CMAKE_SOURCE_DIR}/module-utils/parallel-hashmap" "${CMAKE_SOURCE_DIR}/module-utils" + "${CMAKE_SOURCE_DIR}/module-vfs/include/user" + "${CMAKE_SOURCE_DIR}/module-vfs/include/internal" ) add_library(${PROJECT_NAME} SHARED ${SOURCES}) +target_compile_options( ${PROJECT_NAME} PRIVATE "-Wno-nonnull-compare" ) get_target_property( target_options ${PROJECT_NAME} COMPILE_OPTIONS) list(REMOVE_ITEM target_options "-fsanitize=address") set_property(TARGET ${PROJECT_NAME} PROPERTY COMPILE_OPTIONS ${target_options} ) diff --git a/board/linux/libiosyscalls/include/debug.hpp b/board/linux/libiosyscalls/include/debug.hpp index 91ef591a7d75241c0fc91391e8396eb0da9ab41c..b8a241b904690560aa15875a0f64f22a70fc0a03 100644 --- a/board/linux/libiosyscalls/include/debug.hpp +++ b/board/linux/libiosyscalls/include/debug.hpp @@ -3,19 +3,13 @@ #pragma once -#include -#include - -namespace vfsn::debug::internal { - static inline void trace_syscall( const char* fn) - { - int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...); - real_fprintf = reinterpret_cast(dlsym(RTLD_NEXT, "fprintf")); - real_fprintf(stderr,">>>>>>> CALL FUNC [%s] <<<<<<<\n", fn ); - } -} #ifdef DEBUG_SHARED_LIBRARY_FS_LIB -#define TRACE_SYSCALL() vfsn::debug::internal::trace_syscall(__PRETTY_FUNCTION__) +namespace vfsn::linux::internal { + void debug_trace_syscall(const char* fn, const char* format, ...); +} +#define TRACE_SYSCALL() vfsn::linux::internal::debug_trace_syscall(__PRETTY_FUNCTION__,"") +#define TRACE_SYSCALLN(format,...) vfsn::linux::internal::debug_trace_syscall(__PRETTY_FUNCTION__,format,__VA_ARGS__) #else #define TRACE_SYSCALL() do {} while(0) +#define TRACE_SYSCALLN(format,...) do {} while(0) #endif diff --git a/board/linux/libiosyscalls/include/dirent_support.hpp b/board/linux/libiosyscalls/include/dirent_support.hpp deleted file mode 100644 index a79a6614ada09ed3af367341c1f993f04290d7e8..0000000000000000000000000000000000000000 --- a/board/linux/libiosyscalls/include/dirent_support.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#pragma once - -#include - - -namespace vfsn::linux::internal::diren -{ - struct DIR_ITER { - void *dir_state = nullptr; - char name_state[NAME_MAX+1] = { '\0' }; - }; - - DIR_ITER *diropen(int &_errno_, const char *path); - int dirreset(int &_errno_, DIR_ITER *state); - int dirnext(int &_errno_, DIR_ITER *state); - int dirclose(int &_errno_, DIR_ITER *state); -} // namespace vfsn::internal::dirent diff --git a/board/linux/libiosyscalls/include/internal.hpp b/board/linux/libiosyscalls/include/internal.hpp deleted file mode 100644 index d109e1cce548cddb7761e43512662ac1499b352a..0000000000000000000000000000000000000000 --- a/board/linux/libiosyscalls/include/internal.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once -#include - -struct _FF_FILE; -struct _IO_FILE; - -namespace vfsn::linux::internal -{ - int ff_file_to_fd(_FF_FILE *fil); - _FF_FILE * fd_to_ff_file(int fd); - const char* relative_to_root( char *out_path, size_t out_path_len, const char *inpath ); - bool is_ff_handle(_IO_FILE* descriptor); - bool vfs_is_initialized(); -} diff --git a/board/linux/libiosyscalls/include/iosyscalls.hpp b/board/linux/libiosyscalls/include/iosyscalls.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3bbc7664e70dd25268c5d6ce78b9ce3f3c4e1702 --- /dev/null +++ b/board/linux/libiosyscalls/include/iosyscalls.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once +#include +#include +#include + +namespace vfsn::linux::internal +{ + bool redirect_to_image(); + bool is_image_handle(const FILE* fil); + int native_fd_to_image_fd(int fd); + int image_fd_to_native_fd(int fd); + bool is_image_fd(int fd); + bool redirect_to_image(const char* inpath); + const char* npath_translate(const char* inpath, char *buffer); + + struct FILEX { + int fd {0}; + int error {0}; + int ungetchar {-1}; + }; + FILEX* allocate_filex(int fd); + bool is_filex(const void* fd); + void remove_filex(FILEX *fil); + + template + auto invoke_fs( T Base::*lfs_fun, Args&& ... args) + -> decltype((static_cast(nullptr)->*lfs_fun)(std::forward(args)...)) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + return 0; + } + auto ret = (vfs.get()->*lfs_fun)(std::forward(args)...); + if(ret < 0) { + errno = -ret; + ret = -1; + } + return ret; + } +} + diff --git a/board/linux/libiosyscalls/src/dirent.cpp b/board/linux/libiosyscalls/src/dirent.cpp index e994e7f5cdaa0c90c309e077eb66d08810b3886f..db1a0ce337e30af094017dea28a17e673e008e7b 100644 --- a/board/linux/libiosyscalls/src/dirent.cpp +++ b/board/linux/libiosyscalls/src/dirent.cpp @@ -1,99 +1,156 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include + +#include +#include +#include "debug.hpp" + #include #include #include -#include "dirent_support.hpp" -#include "debug.hpp" -#include +#include +#include struct __dirstream { - long int position; - vfsn::linux::internal::diren::DIR_ITER* dir_data; - struct dirent file_data; + purefs::fs::filesystem::fsdir dirh; + struct dirent dir_data; + size_t position; }; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" extern "C" { using namespace vfsn::linux::internal; DIR *opendir(const char *dirname) { - TRACE_SYSCALL(); - if(!dirname) { + __dirstream* ret {}; + if(!dirname) + { errno = EINVAL; - return nullptr; - } - if(!vfs_is_initialized()) { - errno = EIO; - return nullptr; } - auto dir = new DIR; - char dirbuf[ffconfigMAX_FILENAME]; - dir->dir_data = diren::diropen(errno, relative_to_root(dirbuf,sizeof dirbuf,dirname)); - if (!dir->dir_data) { - delete dir; - return nullptr; + else + { + if( redirect_to_image() ) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) + { + errno = EIO; + } + else + { + ret = new(std::nothrow)__dirstream; + if(!ret) + { + errno = ENOMEM; + } + else + { + ret->position = 0; + ret->dirh = vfs->diropen(dirname); + if(!ret->dirh) + { + delete ret; + errno = EIO; + ret = nullptr; + } + else if(ret->dirh->error()) + { + errno = -ret->dirh->error(); + delete ret; + ret = nullptr; + } + } + } + } + else + { + char tmp[PATH_MAX]; + const auto newpath = npath_translate(dirname,tmp); + auto r_opendir = reinterpret_cast(dlsym(RTLD_NEXT,"opendir")); + ret = r_opendir(newpath); + } } - dir->position = 0; - dir->file_data.d_ino = -1; - dir->file_data.d_name[0] = '\0'; - return dir; + TRACE_SYSCALLN("(%s)=%p errno=%i",dirname,ret,errno); + return ret; } + __asm__(".symver diropen,diropen@GLIBC_2.2.5"); int closedir(DIR *dirp) { - TRACE_SYSCALL(); - if (!dirp) { - errno = EBADF; - return -1; - } - if(!vfs_is_initialized()) { - errno = EIO; - return -1; - } - auto res = diren::dirclose(errno, dirp->dir_data); - delete dirp; - return res; + int ret {}; + do { + if (!dirp) { + errno = EBADF; + ret = -1; + break; + } + if(redirect_to_image()) { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + ret = -1; + break; + } + ret = vfs->dirclose(dirp->dirh); + if(ret < 0) { + errno = -ret; + ret = -1; + } + delete dirp; + } else { + auto r_closedir = reinterpret_cast(dlsym(RTLD_NEXT,"closedir")); + ret = r_closedir(dirp); + } + } while(0); + TRACE_SYSCALLN("(%p)=%i errno=%i", dirp, ret, errno); + return ret; } __asm__(".symver closedir,closedir@GLIBC_2.2.5"); struct dirent *readdir(DIR *dirp) { - TRACE_SYSCALL(); - if (!dirp) { - errno = EBADF; - return nullptr; - } - if(!vfs_is_initialized()) { - errno = EIO; - return nullptr; - } - auto olderrno{errno}; - auto res = diren::dirnext(errno, dirp->dir_data); - auto fff = reinterpret_cast(dirp->dir_data->dir_state); - if (res < 0) { - if (errno == pdFREERTOS_ERRNO_ENMFILE) { - errno = olderrno; + dirent* ret {}; + do { + if (!dirp) { + errno = EBADF; + break; } - return nullptr; - } - dirp->position += 1; - if (strnlen(fff->pcFileName, NAME_MAX) >= sizeof(dirp->file_data.d_name)) { - errno = EOVERFLOW; - return nullptr; - } - dirp->file_data.d_ino = fff->xDirectoryEntry.ulObjectCluster; - dirp->file_data.d_type = (fff->ucAttributes & FF_FAT_ATTR_DIR) ? DT_DIR : DT_REG; - dirp->file_data.d_reclen = std::strlen( fff->pcFileName ); - std::strncpy(dirp->file_data.d_name, fff->pcFileName, sizeof(dirp->file_data.d_name)); - return &dirp->file_data; + if(redirect_to_image()) { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + break; + } + std::string fname; + struct stat stdata; + auto res = vfs->dirnext(dirp->dirh, fname, stdata); + if(res < 0) { + if(res != -ENODATA) { + errno = -res; + } + break; + } else { + if (fname.size() >= sizeof(dirp->dir_data.d_name)) { + errno = EOVERFLOW; + break; + } + dirp->position += 1; + dirp->dir_data.d_ino = stdata.st_ino; + dirp->dir_data.d_type = S_ISREG(stdata.st_mode)?DT_REG:DT_DIR; + dirp->dir_data.d_reclen = fname.size(); + std::strncpy(dirp->dir_data.d_name,fname.c_str(), sizeof(dirp->dir_data.d_name)); + ret = &dirp->dir_data; + } + } else { + auto r_readdir = reinterpret_cast(dlsym(RTLD_NEXT,"readdir")); + ret = r_readdir(dirp); + } + } while(0); + TRACE_SYSCALLN("(%p)=%p errno=%i", dirp,ret,errno); + return ret; } __asm__(".symver readdir,readdir@GLIBC_2.2.5"); @@ -104,30 +161,36 @@ extern "C" { errno = EBADF; return -1; } - if(!vfs_is_initialized()) { - errno = EIO; - return -1; - } - auto olderrno{errno}; - auto res = diren::dirnext(errno, dirp->dir_data); - auto fff = reinterpret_cast(dirp->dir_data->dir_state); - if (res < 0) { - res = errno; - if (errno == pdFREERTOS_ERRNO_ENMFILE) { - res = 0; + if(redirect_to_image()) { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + return -1; } - errno = olderrno; - return res; - } - dirp->position += 1; - if (strnlen(fff->pcFileName, NAME_MAX) >= sizeof(entry->d_name)) { - return EOVERFLOW; + std::string fname; + struct stat stdata; + auto res = vfs->dirnext(dirp->dirh, fname, stdata); + if(res < 0) { + errno = -res; + res = -1; + return res; + } else { + if (fname.size() >= sizeof(entry->d_name)) { + errno = EOVERFLOW; + return -1; + } + dirp->position += 1; + entry->d_ino = stdata.st_ino; + entry->d_type = S_ISREG(stdata.st_mode)?DT_REG:DT_DIR; + entry->d_reclen = fname.size(); + std::strncpy(entry->d_name,fname.c_str(), sizeof(entry->d_name)); + *result = entry; + return 0; + } + } else { + auto r_readdir_r = reinterpret_cast(dlsym(RTLD_NEXT,"readdir_r")); + return r_readdir_r(dirp,entry,result); } - entry->d_ino = fff->xDirectoryEntry.ulObjectCluster; - entry->d_type = (fff->ucAttributes & FF_FAT_ATTR_DIR) ? DT_DIR : DT_REG; - std::strncpy(entry->d_name, fff->pcFileName, sizeof(entry->d_name)); - *result = entry; - return 0; } __asm__(".symver readdir_r,readdir_r@GLIBC_2.2.5"); @@ -138,12 +201,23 @@ extern "C" { errno = EBADF; return; } - if(!vfs_is_initialized()) { - errno = EIO; - return; + if(redirect_to_image()) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + return; + } + auto res = vfs->dirreset(dirp->dirh); + if(res < 0) { + return; + } + dirp->position = 0; + } + else + { + auto r_rewinddir = reinterpret_cast(dlsym(RTLD_NEXT,"rewinddir")); + r_rewinddir(dirp); } - diren::dirreset(errno, dirp->dir_data); - dirp->position = 0; } __asm__(".symver rewinddir,rewinddir@GLIBC_2.2.5"); @@ -154,19 +228,29 @@ extern "C" { errno = EBADF; return; } - if(!vfs_is_initialized()) { - errno = EIO; - return; - } - if (loc < 0) { - return; - } - if (dirp->position > loc) { - diren::dirreset(errno, dirp->dir_data); - dirp->position = 0; + if( redirect_to_image() ) + { + if (loc < 0) { + return; + } + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + return; + } + if (long(dirp->position) > loc) { + vfs->dirreset(dirp->dirh); + dirp->position = 0; + } + std::string name; + struct stat st; + while ((long(dirp->position) < loc) && (vfs->dirnext(dirp->dirh,name,st))>=0) { + dirp->position += 1; + } } - while ((dirp->position < loc) && (diren::dirnext(errno, dirp->dir_data) >= 0)) { - dirp->position += 1; + else + { + auto r_seekdir = reinterpret_cast(dlsym(RTLD_NEXT,"seekdir")); + r_seekdir(dirp,loc); } } __asm__(".symver seekdir,seekdir@GLIBC_2.2.5"); @@ -178,13 +262,17 @@ extern "C" { errno = EBADF; return -1; } - if(!vfs_is_initialized()) { - errno = EIO; - return -1; + if( redirect_to_image() ) + { + return dirp->position; + } + else + { + auto r_telldir = reinterpret_cast(dlsym(RTLD_NEXT,"telldir")); + return r_telldir(dirp); } - return dirp->position; } __asm__(".symver telldir,telldir@GLIBC_2.2.5"); } -#pragma GCC diagnostic pop + diff --git a/board/linux/libiosyscalls/src/dirent_support.cpp b/board/linux/libiosyscalls/src/dirent_support.cpp deleted file mode 100644 index 85ea7747e2ccbb3331c6876d6cba7ab0550523f6..0000000000000000000000000000000000000000 --- a/board/linux/libiosyscalls/src/dirent_support.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "dirent_support.hpp" -#include -#include -#include -#include -#include - - -namespace vfsn::linux::internal::diren -{ - DIR_ITER *diropen(int &_errno_, const char *path) - { - FF_Stat_t fs; - if (ff_stat(path, &fs)) { - _errno_ = stdioGET_ERRNO(); - if (_errno_ == EFAULT) - _errno_ = ENOENT; - return nullptr; - } - if (!(fs.st_mode & FF_IFDIR)) { - _errno_ = ENOTDIR; - return nullptr; - } - auto ret = new (std::nothrow) DIR_ITER; - if (!ret) { - _errno_ = ENOMEM; - return nullptr; - } - ret->dir_state = nullptr; - std::strncpy(ret->name_state, path, sizeof(ret->name_state)); - return ret; - } - - int dirreset(int &_errno_, DIR_ITER *state) - { - if( !state ) { - _errno_ = EINVAL; - return -1; - } - if (state->dir_state) { - delete reinterpret_cast(state->dir_state); - state->dir_state = nullptr; - _errno_ = 0; - return 0; - } - else { - _errno_ = EBADF; - return -1; - } - } - int dirnext(int &_errno_, DIR_ITER *state) - { - int ret; - if(!state) { - _errno_ = EINVAL; - return -1; - } - if (!state->dir_state) { - auto fdd = new (std::nothrow) FF_FindData_t; - if (!fdd) { - _errno_ = ENOMEM; - return -1; - } - std::memset(fdd, 0, sizeof(*fdd)); - ret = ff_findfirst(state->name_state, fdd); - state->dir_state = fdd; - } - else { - auto fdd = static_cast(state->dir_state); - ret = ff_findnext(fdd); - } - _errno_ = stdioGET_ERRNO(); - if (_errno_ == EFAULT) - _errno_ = ENOENT; - return ret; - } - - int dirclose(int &_errno_, DIR_ITER *state) - { - if(!state) { - _errno_ = 0; - return 0; - } - if (state->dir_state) { - delete reinterpret_cast(state->dir_state); - } - delete state; - _errno_ = 0; - return 0; - } -} // namespace vfsn::internal::dirent diff --git a/board/linux/libiosyscalls/src/iosyscalls.cpp b/board/linux/libiosyscalls/src/iosyscalls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02bfd8baec25a5a7c3aa12ab16a41776633bcd76 --- /dev/null +++ b/board/linux/libiosyscalls/src/iosyscalls.cpp @@ -0,0 +1,164 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr auto ENV_NAME = "IOSYSCALLS_REDIRECT_TO_IMAGE"; + constexpr auto FIRST_FILEDESC = 64'566'756; + bool g_readed = false ; + bool g_redirect = false; + constexpr const char * ALLOWED_PATHS[] = { + "/dev/", + "/etc/", + "/sys/", + "PurePhone.img", + nullptr, + }; + constexpr const char * EXCLUDED_PATHS[] = { + "/sys/user", + "/sys/factory-test", + "/sys/current/assets", + "/sys/updates", + nullptr, + }; + + constexpr const char * TRANSLATION_PATHS[] = + { + "sys/user", + "sys/factory-test", + "assets", + "sys/updates", + nullptr + }; + + pthread_mutex_t g_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + phmap::flat_hash_set g_fdlist; +} + +namespace vfsn::linux::internal +{ + bool redirect_to_image() + { + if(!g_readed) { + const auto env = std::getenv(ENV_NAME); + g_redirect = env && !std::strcmp(env,"1"); + g_readed = true; + } + return g_redirect; + } + + bool redirect_to_image(const char* inpath) + { + auto native_redirect = redirect_to_image(); + auto redirect = native_redirect; + if(native_redirect) { + for(auto path=ALLOWED_PATHS; *path; ++path) { + if( std::strstr(inpath,*path)==inpath) { + redirect = false; + break; + } + } + } + if(native_redirect && !redirect) + { + for(auto path=EXCLUDED_PATHS; *path; ++path) { + if( std::strstr(inpath,*path)==inpath) { + redirect = true; + break; + } + } + } + return redirect; + } + + const char* npath_translate(const char* inpath, char *buffer) + { + for(size_t trans_pos=0; EXCLUDED_PATHS[trans_pos]; ++trans_pos) { + if( std::strstr(inpath,EXCLUDED_PATHS[trans_pos])==inpath) { + std::strncpy(buffer,TRANSLATION_PATHS[trans_pos],PATH_MAX); + std::strncat(buffer,inpath+std::strlen(EXCLUDED_PATHS[trans_pos]), PATH_MAX); + return buffer; + } + } + return inpath; + } + + bool is_image_handle(const FILE* fil) + { + return false; + } + + int native_fd_to_image_fd(int fd) + { + return FIRST_FILEDESC + fd; + } + + int image_fd_from_native_fd(int fd) + { + if(fd < FIRST_FILEDESC ) { + return -1; + } else { + return fd - FIRST_FILEDESC; + } + } + + bool is_image_fd(int fd) + { + return fd >= FIRST_FILEDESC; + } + + FILEX* allocate_filex(int fd) + { + auto ret = new FILEX; + ret->fd = fd; + pthread_mutex_lock(&g_lock); + g_fdlist.emplace( ret ); + pthread_mutex_unlock(&g_lock); + return ret; + } + + bool is_filex(const void* fd) + { + if(fd==nullptr) { + return false; + } + pthread_mutex_lock(&g_lock); + auto fres = g_fdlist.find(reinterpret_cast(fd)); + auto isfilex = ( fres != g_fdlist.end() ); + pthread_mutex_unlock(&g_lock); + return isfilex; + } + + void remove_filex(FILEX *fil) + { + pthread_mutex_lock(&g_lock); + auto fres = g_fdlist.find(fil); + if(fres != g_fdlist.end()) + { + g_fdlist.erase(fres); + delete fil; + } + pthread_mutex_unlock(&g_lock); + } + + void debug_trace_syscall(const char* fn, const char* format, ...) + { + auto rvprint = reinterpret_cast(dlsym(RTLD_NEXT, "vfprintf")); + auto rprint = reinterpret_cast(dlsym(RTLD_NEXT, "fprintf")); + rprint(stderr,">>>>>>> IOFUNC: [%s] ", fn); + va_list args; + va_start(args, format); + rvprint(stderr, format, args); + va_end(args); + rprint(stderr," >>>>>>>>>>>\n"); + } +} diff --git a/board/linux/libiosyscalls/src/syscalls_posix.cpp b/board/linux/libiosyscalls/src/syscalls_posix.cpp index 070eca5eb9e0b6a0b13eb057805cfb8cfc233092..aa985b51684503f2ee64c59645817cc79e2babb0 100644 --- a/board/linux/libiosyscalls/src/syscalls_posix.cpp +++ b/board/linux/libiosyscalls/src/syscalls_posix.cpp @@ -1,8 +1,7 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "internal.hpp" -#include +#include #include #include #include @@ -10,159 +9,136 @@ #include #include #include +#include #include +#include +#include + #include "debug.hpp" +#include -//NOTE: It will be removed in later stage -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" namespace { int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...); - int (*real_xstat)(int ver, const char * path, struct stat * stat_buf); - int (*real_lxstat)(int ver, const char * path, struct stat * stat_buf); - int (*real_fxstat)(int ver, int fildes, struct stat * stat_buf); - int (*real_fcntl)(int __fd, int __cmd, ...); - int (*real_fcntl64) (int __fd, int __cmd, ...); void __attribute__((constructor)) _lib_posix_initialize() { real_fprintf = reinterpret_cast(dlsym(RTLD_NEXT, "fprintf")); - real_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__xstat")); - real_lxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__lxstat")); - real_fxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__fxstat")); - real_fcntl = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl")); - real_fcntl64 = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl64")); - if(!real_fprintf || !real_xstat || !real_lxstat || !real_fxstat - || !real_fcntl || !real_fcntl64 ) + if(!real_fprintf) { abort(); } } - int ff_cstat(const char *file, struct stat *pstat) - { - namespace vfs = vfsn::linux::internal; - char filebuf[ffconfigMAX_FILENAME]; - FF_Stat_t stat_ff; - auto ret = ff_stat(vfs::relative_to_root(filebuf,sizeof filebuf,file), &stat_ff); - std::memset(pstat, 0, sizeof(*pstat)); - if (!ret && pstat) { - pstat->st_ino = stat_ff.st_ino; - pstat->st_size = stat_ff.st_size; - pstat->st_dev = stat_ff.st_dev; - // Linux mode compat - if (stat_ff.st_mode == FF_IFREG) - pstat->st_mode = S_IFREG | 0666; - if (stat_ff.st_mode == FF_IFDIR) - pstat->st_mode = S_IFDIR | 0777; - } - errno = stdioGET_ERRNO(); - // NOTE: ff_stdio uses wrong errno NOADDRESS - if (errno == EFAULT) - errno = ENOENT; - return ret; - } } + extern "C" { - namespace vfs = vfsn::linux::internal; + using namespace vfsn::linux::internal; int link(const char *oldpath, const char *newpath) { TRACE_SYSCALL(); - errno = ENOSYS; - real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); - return -1; + if(redirect_to_image(oldpath)) + { + errno = ENOSYS; + real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); + return -1; + } + else + { + auto r_link = reinterpret_cast(dlsym(RTLD_NEXT,"link")); + char tmp[PATH_MAX], tmp2[PATH_MAX]; + const auto oldp = npath_translate(oldpath,tmp); + const auto newp = npath_translate(newpath,tmp2); + return r_link(oldp,newp); + } } __asm__(".symver link,link@GLIBC_2.2.5"); int unlink(const char *name) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + if(redirect_to_image(name)) + { + return invoke_fs(&purefs::fs::filesystem::unlink, name); + } + else + { + char tmp[PATH_MAX]; + const auto path = npath_translate(name,tmp); + auto r_unlink = reinterpret_cast(dlsym(RTLD_NEXT,"unlink")); + return r_unlink(path); } - char namebuf[ffconfigMAX_FILENAME]; - auto ret = ff_remove(vfs::relative_to_root(namebuf,sizeof namebuf, name)); - if (ret && stdioGET_ERRNO() == EISDIR) - ret = ff_deltree(vfs::relative_to_root(namebuf,sizeof namebuf,name), nullptr, nullptr); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver unlink,unlink@GLIBC_2.2.5"); - int stat(const char *file, struct stat *pstat) { + int stat(const char *file, struct stat *pstat) + { TRACE_SYSCALL(); - int ret {}; - if(!vfs::vfs_is_initialized()) { - ret = -1; - } else { - ret = ff_cstat(file, pstat); + if(redirect_to_image(file)) + { + return invoke_fs(&purefs::fs::filesystem::stat, file, *pstat); } - if(ret) { - real_fprintf(stderr,"WARNING: redirecting stat(%s) to the linux fs\n",file); - ret = real_xstat(1,file,pstat); + else + { + char tmp[PATH_MAX]; + const auto newfile = npath_translate(file,tmp); + auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__xstat")); + return r_xstat(1,newfile,pstat); } - return ret; } __asm__(".symver stat,stat@GLIBC_2.2.5"); int fstat(int fd, struct stat *pstat) { TRACE_SYSCALL(); - FF_FILE* fil; - if(!vfs::vfs_is_initialized()) { - fil = nullptr; - } else { - fil = vfsn::linux::internal::fd_to_ff_file(fd); - } - if(!fil) { - real_fprintf(stderr,"WARNING: redirecting fstat(%i) to the linux fs\n",fd); - return real_fxstat(1,fd,pstat); - } - std::memset(pstat, 0, sizeof(*pstat)); - pstat->st_ino = fil->ulObjectCluster; - pstat->st_size = fil->ulFileSize; - pstat->st_dev = 0; - pstat->st_mode = S_IFREG | 0666; - errno = 0; - return 0; + if(is_image_fd(fd)) + { + return invoke_fs(&purefs::fs::filesystem::fstat,fd,*pstat); + } + else + { + auto r_fxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__fxstat")); + return r_fxstat(1,fd,pstat); + } } __asm__(".symver fstat,fstat@GLIBC_2.2.5"); int lstat(const char *pathname, struct stat *statbuf) { TRACE_SYSCALL(); - int ret; - if(!vfs::vfs_is_initialized()) { - ret = -1; - } else { - ret = ff_cstat(pathname, statbuf); + if(redirect_to_image(pathname)) + { + return invoke_fs(&purefs::fs::filesystem::stat, pathname, *statbuf); } - if(ret) { - real_fprintf(stderr,"WARNING: redirecting lstat(%s) to the linux fs\n",pathname); - ret = real_lxstat(1,pathname,statbuf); + else + { + char tmp[PATH_MAX]; + const auto newpath = npath_translate(pathname,tmp); + auto r_lxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__lxstat")); + return r_lxstat(1,newpath,statbuf); } - return ret; } __asm__(".symver lstat,lstat@GLIBC_2.2.5"); int fcntl(int fd, int cmd, ... /* arg */ ) { TRACE_SYSCALL(); - if( vfs::fd_to_ff_file(fd) ) { + if(is_image_fd(fd)) + { TRACE_SYSCALL(); errno = ENOSYS; real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); return -1; - } else { + } + else + { uintptr_t param; va_list args; + auto r_fcntl = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl")); va_start(args,cmd); param = va_arg(args,uintptr_t); - auto ret = real_fcntl(fd, cmd, param ); + auto ret = r_fcntl(fd, cmd, param ); va_end(args); - real_fprintf(stderr,"WARNING: redirecting fcntl (%i) to the linux fs\n",fd); return ret; } } @@ -171,7 +147,8 @@ extern "C" { int fcntl64(int fd, int cmd, ... /* arg */ ) { TRACE_SYSCALL(); - if( vfs::fd_to_ff_file(fd) ) { + if(is_image_fd(fd)) + { TRACE_SYSCALL(); real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); errno = ENOSYS; @@ -179,11 +156,11 @@ extern "C" { } else { uintptr_t param; va_list args; + auto r_fcntl = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl64")); va_start(args,cmd); param = va_arg(args,uintptr_t); - auto ret = real_fcntl(fd, cmd, param ); + auto ret = r_fcntl(fd, cmd, param); va_end(args); - real_fprintf(stderr,"WARNING: redirecting fcntl (%i) to the linux fs\n",fd); return ret; } } @@ -192,52 +169,78 @@ extern "C" { int chdir(const char *path) { TRACE_SYSCALL(); - char pathbuf[ffconfigMAX_FILENAME]; - int ret; - if(!vfs::vfs_is_initialized()) + if(redirect_to_image(path)) { - ret = -1; - errno = -EIO; + return invoke_fs(&purefs::fs::filesystem::chdir, path); } - else { - ret = ff_chdir(vfs::relative_to_root(pathbuf,sizeof pathbuf,path)); - errno = stdioGET_ERRNO(); + else + { + char tmp[PATH_MAX]; + const auto newpath = npath_translate(path,tmp); + auto r_chdir = reinterpret_cast(dlsym(RTLD_NEXT,"chdir")); + return r_chdir(newpath); } - return ret; } __asm__(".symver chdir,chdir@GLIBC_2.2.5"); + int fchdir(int fd) { TRACE_SYSCALL(); - errno = ENOSYS; - real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); - return -1; + if(is_image_fd(fd)) + { + errno = ENOSYS; + real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); + return -1; + } + else + { + auto r_fchdir = reinterpret_cast(dlsym(RTLD_NEXT,"fchdir")); + return r_fchdir(fd); + } } __asm__(".symver fchdir,fchdir@GLIBC_2.2.5"); char *getcwd(char *buf, size_t size) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return nullptr; + if(redirect_to_image()) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + return nullptr; + } + auto xwd = vfs->getcwd(); + xwd.copy(buf,size); + return buf; + } + else + { + auto r_getcwd = reinterpret_cast(dlsym(RTLD_NEXT,"getcwd")); + return r_getcwd(buf,size); } - auto cwd = ff_getcwd(buf, size); - errno = stdioGET_ERRNO(); - return cwd; } __asm__(".symver getcwd,getcwd@GLIBC_2.2.5"); char *getwd(char *buf) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return nullptr; + if(redirect_to_image()) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + return nullptr; + } + auto xwd = vfs->getcwd(); + xwd.copy(buf,xwd.size()); + return buf; + } + else + { + auto r_getwd = reinterpret_cast(dlsym(RTLD_NEXT,"getwd")); + return r_getwd(buf); } - auto cwd = ff_getcwd(buf, ffconfigMAX_FILENAME ); - errno = stdioGET_ERRNO(); - return cwd; } __asm__(".symver getwd,getwd@GLIBC_2.2.5"); @@ -245,14 +248,24 @@ extern "C" { char *get_current_dir_name(void) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return nullptr; - } - auto buf = new char[ffconfigMAX_FILENAME]; - auto cwd = ff_getcwd(buf, ffconfigMAX_FILENAME ); - errno = stdioGET_ERRNO(); - return cwd; + if(redirect_to_image()) + { + auto vfs = purefs::subsystem::vfs_core(); + if(!vfs) { + errno = EIO; + return nullptr; + } + auto xwd = vfs->getcwd(); + auto ret = new char[xwd.size()+1]; + xwd.copy(ret,xwd.size()); + ret[xwd.size()] = '\0'; + return ret; + } + else + { + auto r_getrd = reinterpret_cast(dlsym(RTLD_NEXT,"get_current_dir_name")); + return r_getrd(); + } } __asm__(".symver get_current_dir_name,get_current_dir_name@GLIBC_2.2.5"); @@ -260,67 +273,81 @@ extern "C" { int rename(const char *oldpath, const char *newpath) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + if(redirect_to_image(oldpath)) + { + return invoke_fs(&purefs::fs::filesystem::rename, oldpath, newpath); + } + else + { + char tmp[PATH_MAX], tmp2[PATH_MAX]; + const auto oldp = npath_translate(oldpath,tmp); + const auto newp = npath_translate(newpath,tmp2); + auto r_rename = reinterpret_cast(dlsym(RTLD_NEXT,"rename")); + return r_rename(oldp,newp); } - char oldpbuf[ffconfigMAX_FILENAME]; - char newpbuf[ffconfigMAX_FILENAME]; - auto ret = ff_rename(vfs::relative_to_root(oldpbuf,sizeof oldpbuf, oldpath), - vfs::relative_to_root(newpbuf,sizeof newpbuf,newpath), true); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver rename,rename@GLIBC_2.2.5"); - int mkdir(const char *pathname, mode_t ) + int mkdir(const char *pathname, mode_t mode) { - TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + if(redirect_to_image(pathname)) + { + return invoke_fs(&purefs::fs::filesystem::mkdir, pathname, mode); + } + else + { + char tmp[PATH_MAX]; + const auto path = npath_translate(pathname,tmp); + auto r_mkdir = reinterpret_cast(dlsym(RTLD_NEXT,"mkdir")); + return r_mkdir(path,mode); } - char pathbuf[ffconfigMAX_FILENAME]; - auto ret = ff_mkdir(vfs::relative_to_root(pathbuf,sizeof pathbuf,pathname)); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver mkdir,mkdir@GLIBC_2.2.5"); int chmod(const char *pathname, mode_t mode) { TRACE_SYSCALL(); - errno = ENOSYS; - real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); - return -1; + if(redirect_to_image(pathname)) + { + return invoke_fs(&purefs::fs::filesystem::chmod,pathname,mode); + } + else + { + char tmp[PATH_MAX]; + const auto path = npath_translate(pathname,tmp); + auto r_chmod = reinterpret_cast(dlsym(RTLD_NEXT,"chmod")); + return r_chmod(path,mode); + } } __asm__(".symver chmod,chmod@GLIBC_2.2.5"); int fchmod(int fd, mode_t mode) { TRACE_SYSCALL(); - errno = ENOSYS; - real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); - return -1; + if(is_image_fd(fd)) + { + return invoke_fs(&purefs::fs::filesystem::fchmod,fd,mode); + } + else + { + auto r_fchmod = reinterpret_cast(dlsym(RTLD_NEXT,"fchmod")); + return r_fchmod(fd,mode); + } } __asm__(".symver fchmod,fchmod@GLIBC_2.2.5"); int fsync(int fd) { TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + if(is_image_fd(fd)) + { + return invoke_fs(&purefs::fs::filesystem::fsync, fd); } - auto fil = vfsn::linux::internal::fd_to_ff_file(fd); - if (!fil) { - LOG_ERROR("Unable to find handle %i", fd); - errno = EBADF; - return -1; + else + { + auto r_fsync = reinterpret_cast(dlsym(RTLD_NEXT,"fsync")); + return r_fsync(fd); } - auto ret = ff_fflush(fil); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fsync,fsync@GLIBC_2.2.5"); @@ -334,9 +361,18 @@ extern "C" { int symlink(const char *target, const char *linkpath) { TRACE_SYSCALL(); - errno = ENOSYS; - real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); - return -1; + if(redirect_to_image(target)) + { + return invoke_fs(&purefs::fs::filesystem::symlink,target,linkpath); + } + else + { + char tmp[PATH_MAX], tmp2[PATH_MAX]; + const auto tgtp = npath_translate(target,tmp); + const auto linp = npath_translate(linkpath,tmp2); + auto r_symlink = reinterpret_cast(dlsym(RTLD_NEXT,"symlink")); + return r_symlink(tgtp,linp); + } } __asm__(".symver symlink,symlink@GLIBC_2.2.5"); @@ -359,55 +395,44 @@ extern "C" { int __xstat(int ver, const char * path, struct stat * stat_buf) { - TRACE_SYSCALL(); - if(!dlsym(RTLD_DEFAULT, "ff_stat")) { - return real_xstat( ver,path,stat_buf ); - } - else { - int ret = stat( path, stat_buf ); - if(ret) { - real_fprintf(stderr,"WARNING: redirecting __xstat(%s) to the linux fs\n",path); - ret = real_xstat( ver,path,stat_buf ); - } - return ret; + if( redirect_to_image(path) ) + { + return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf); + } + else + { + char tmp[PATH_MAX]; + const auto newp = npath_translate(path,tmp); + auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__xstat")); + return r_xstat(ver,newp,stat_buf); } } int __lxstat(int ver, const char * path, struct stat * stat_buf) { - TRACE_SYSCALL(); - if(!dlsym(RTLD_DEFAULT, "ff_stat")) { - return real_xstat( ver,path,stat_buf ); + if( redirect_to_image(path) ) + { + return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf); } - else { - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - int ret = ff_cstat(path, stat_buf); - if(ret) { - real_fprintf(stderr,"WARNING: redirecting __lxstat(%s) to the linux fs\n",path); - ret = real_lxstat(ver,path,stat_buf ); - } - return ret; + else + { + char tmp[PATH_MAX]; + const auto newp = npath_translate(path,tmp); + auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__lxstat")); + return r_xstat(ver,newp,stat_buf); } } int __fxstat(int ver, int fildes, struct stat * stat_buf) { - TRACE_SYSCALL(); - if(!dlsym(RTLD_DEFAULT, "ff_stat")) { - return real_fxstat( ver,fildes,stat_buf ); - } - else { - int ret = fstat(fildes, stat_buf); - if(ret) { - real_fprintf(stderr,"WARNING: redirecting __fxstat(%i) to the linux fs\n",fildes); - ret = real_fxstat( ver,fildes,stat_buf ); - } - return ret; + if( is_image_fd(fildes) ) + { + return invoke_fs(&purefs::fs::filesystem::fstat, fildes, *stat_buf); + } + else + { + auto r_fxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__fxstat")); + return r_fxstat(ver,fildes,stat_buf); } } - } -#pragma GCC diagnostic pop diff --git a/board/linux/libiosyscalls/src/syscalls_scan_family.cpp b/board/linux/libiosyscalls/src/syscalls_scan_family.cpp index 65c70a2d5621b59a38d9c4b902af2bd6ad1cf2cb..d5b9b8f545bd2ac60ae89a86e6d3147a93c0b124 100644 --- a/board/linux/libiosyscalls/src/syscalls_scan_family.cpp +++ b/board/linux/libiosyscalls/src/syscalls_scan_family.cpp @@ -1,12 +1,11 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -//#include -#include +#include #include #include +#include #include "debug.hpp" -#include "internal.hpp" +#include #include namespace @@ -26,13 +25,28 @@ namespace } } -namespace { - int ic(FF_FILE *fp) +namespace +{ + + using namespace vfsn::linux::internal; + int ic(FILEX *fp) { char ch; - return ff_fread( &ch, 1, 1, fp); + if(fp->ungetchar>0) + { + ch = fp->ungetchar; + fp->ungetchar = -1; + return 0; + } + else + { + auto ret = invoke_fs(&purefs::fs::filesystem::read,fp->fd,&ch,1); + fp->error = errno; + return ret==1?0:ret; + } } - int istr(FF_FILE *fp, char *dst, int wid) + + int istr(FILEX *fp, char *dst, int wid) { char *d = dst; int c; @@ -40,11 +54,11 @@ namespace { *d++ = c; } *d = '\0'; - ungetc(c, reinterpret_cast(fp)); + //ungetc(c, fp); return d == dst; } /* t is 1 for char, 2 for short, 4 for int, and 8 for long */ - int iint(FF_FILE *fp, void *dst, int t, int wid) + int iint(FILEX *fp, void *dst, int t, int wid) { long n = 0; int c; @@ -79,60 +93,47 @@ namespace { return 0; } } -extern "C" { +extern "C" +{ - namespace vfs = vfsn::linux::internal; + using namespace vfsn::linux::internal; int ungetc (int __c, FILE *__stream) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - real_fprintf(stderr,"WARNING: redirecting ungetc(%p) to the linux fs\n",__stream); + if(!is_filex(__stream)) + { return real_ungetc(__c,__stream); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - int ret = ff_fseek(reinterpret_cast(__stream), -1, SEEK_CUR ); - if( ret ) { - errno = stdioGET_ERRNO(); - return ret; - } - char ch = __c; - ret = ff_fwrite(&ch, 1, 1, reinterpret_cast(__stream) ); - if(ret!=1) { - errno = stdioGET_ERRNO(); - return -1; + else + { + auto fx = reinterpret_cast(__stream); + fx->ungetchar = __c; + return 0; } - errno = stdioGET_ERRNO(); - return 0; } __asm__(".symver ungetc,vfscanf@GLIBC_2.2.5"); int vfscanf (FILE *__restrict fp, const char *__restrict fmt, __gnuc_va_list ap) { - if(!vfs::is_ff_handle(fp)) { - real_fprintf(stderr,"WARNING: redirecting fscanf(%p) to the linux fs\n",fp); + if(!is_filex(fp)) + { return real_vfscanf(fp,fmt,ap); } TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } int ret = 0; int t, c; int wid = 1 << 20; + auto fx = reinterpret_cast(fp); while (*fmt) { while (isspace(static_cast(*fmt))) { fmt++; } - while (isspace(c = ic(reinterpret_cast(fp)))) + while (isspace(c = ic(fx))) ; ungetc(c, fp); while (*fmt && *fmt != '%' && !isspace((unsigned char) *fmt)) - if (*fmt++ != ic(reinterpret_cast(fp))) + if (*fmt++ != ic(fx)) return ret; if (*fmt != '%') continue; @@ -154,12 +155,12 @@ extern "C" { switch (*fmt++) { case 'u': case 'd': - if (iint(reinterpret_cast(fp), va_arg(ap, long *), t, wid)) + if (iint((fx), va_arg(ap, long *), t, wid)) return ret; ret++; break; case 's': - if (istr(reinterpret_cast(fp), va_arg(ap, char *), wid)) + if (istr((fx), va_arg(ap, char *), wid)) return ret; ret++; break; diff --git a/board/linux/libiosyscalls/src/syscalls_stdio.cpp b/board/linux/libiosyscalls/src/syscalls_stdio.cpp index c90ab20cd10d1df02130a83310bacdfe9950aa3c..94e9e981a5b52f123551291f19ac883c39884f21 100644 --- a/board/linux/libiosyscalls/src/syscalls_stdio.cpp +++ b/board/linux/libiosyscalls/src/syscalls_stdio.cpp @@ -3,18 +3,16 @@ #include #include -#include "ff_stdio.h" #include +#include #include #include #include -#include "internal.hpp" +#include #include "debug.hpp" - - -//NOTE: It will be removed in later stage -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#include +#include +#include namespace { @@ -43,9 +41,6 @@ namespace long int (*real_ftell) (FILE *__stream) __wur; void (*real_rewind) (FILE *__stream); - std::unordered_map g_fd_map; - std::recursive_mutex g_mutex; - internal::handle_mapper g_handles; void __attribute__((constructor)) _lib_stdio_initialize() { @@ -83,73 +78,63 @@ namespace abort(); } } -} - -namespace vfsn::linux::internal { - namespace { - constexpr auto FIRST_FILEDESC = 64'566'756; - } - // Convert ff_file to standard fd - int ff_file_to_fd( FF_FILE* fil ) + auto fopen_to_open_flags(std::string_view flags) { - std::lock_guard _lck(g_mutex); - const auto it = g_fd_map.find(fil); - return ( it != g_fd_map.end() )?(it->second):(-1); - } - // Convert standard fd for ff file - FF_FILE* fd_to_ff_file( int fd ) - { - std::lock_guard _lck(g_mutex); - if (fd < FIRST_FILEDESC) { - return nullptr; + int ret = 0; + if(!flags.compare("r")) { + ret = O_RDONLY; } - if( !g_handles.exists(fd-FIRST_FILEDESC) ) { - return nullptr; + else if(!flags.compare("w")) { + ret = O_WRONLY | O_CREAT | O_TRUNC; } - return g_handles[fd-FIRST_FILEDESC]; - } - // Check if it is our internal FILE* object - bool is_ff_handle(FILE* descriptor) { - std::lock_guard _lck(g_mutex); - const auto it = g_fd_map.find(reinterpret_cast(descriptor)); - return it != g_fd_map.end(); + else if(!flags.compare("a")) + { + ret = O_WRONLY | O_CREAT | O_APPEND; + } + else if(!flags.compare("r+")) + { + ret = O_RDWR; + } + else if(!flags.compare("w+")) + { + ret = O_RDWR | O_CREAT | O_TRUNC; + } + else if(!flags.compare("a+")) + { + ret = O_RDWR | O_CREAT | O_APPEND; + } + return ret; } - } + extern "C" { - namespace vfs = vfsn::linux::internal; + using namespace vfsn::linux::internal; + FILE *fopen(const char *pathname, const char *mode) { - TRACE_SYSCALL(); - char pathbuf[ffconfigMAX_FILENAME]; - FF_FILE* ret {}; - if(!vfs::vfs_is_initialized()) { - ret = nullptr; - } else { - ret = ff_fopen(vfs::relative_to_root(pathbuf,sizeof pathbuf,pathname), mode); - } - if(ret) { - std::lock_guard _lck(g_mutex); - const auto fd = g_handles.insert(ret) + vfs::FIRST_FILEDESC; - g_fd_map.insert(std::make_pair(ret,fd)); - } else { - auto ret = real_fopen(pathname,mode); - real_fprintf(stderr, - "WARNING: redirecting fopen(%s) to the Linux fs. Native FILE*: %p\n", - pathname, ret - ); - return ret; + FILE* ret {}; + if(redirect_to_image(pathname)) + { + const auto fd = invoke_fs(&purefs::fs::filesystem::open, pathname, fopen_to_open_flags(mode),0644); + if(fd >= 0) { + ret = reinterpret_cast(allocate_filex(fd)); + } + } + else + { + char tmp[PATH_MAX]; + const auto path = npath_translate(pathname,tmp); + ret = real_fopen(path,mode); } - errno = stdioGET_ERRNO(); - return reinterpret_cast(ret); + TRACE_SYSCALLN("(%s,%s)=%p", pathname, mode, ret); + return ret; } __asm__(".symver fopen,fopen@GLIBC_2.2.5"); FILE *fopen64(const char *pathname, const char *mode) { - TRACE_SYSCALL(); return fopen(pathname,mode); } __asm__(".symver fopen64,fopen64@GLIBC_2.2.5"); @@ -157,32 +142,31 @@ extern "C" int fclose(FILE *__stream) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - real_fprintf(stderr,"WARNING: redirecting fclose(%p) to the Linux fs.\n", __stream); - return real_fclose(__stream); - } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - auto ret = ff_fclose(reinterpret_cast(__stream)); + if(is_filex(__stream)) { - std::lock_guard _lck(g_mutex); - const auto it = g_fd_map.find(reinterpret_cast(__stream)); - if( it != g_fd_map.end() ) { - g_handles.remove(it->second - vfs::FIRST_FILEDESC); - g_fd_map.erase(it); + auto fx = reinterpret_cast(__stream); + auto ret = invoke_fs(&purefs::fs::filesystem::close, fx->fd); + if(!ret) + { + remove_filex(fx); + } + else + { + fx->error = errno; } + return ret; + } + else + { + return real_fclose(__stream); } - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fclose,fclose@GLIBC_2.2.5"); FILE *fdopen(int __fd, const char *__modes) __THROW { TRACE_SYSCALL(); - real_fprintf(stderr, "unimplemented call %s\n", __PRETTY_FUNCTION__ ); + real_fprintf(stderr, "unimplemented call %s\n", __PRETTY_FUNCTION__); errno = ENOTSUP; return nullptr; } @@ -190,16 +174,34 @@ extern "C" int feof(FILE *__stream) __THROW { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_feof(__stream); + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + do { + const auto curr = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR); + if(curr<0) { + ret = curr; + break; + } + const auto ends = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_END); + if(ends<0) { + ret = ends; + break; + } + const auto restored = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,curr,SEEK_SET); + if(restored<0) { + ret = restored; + break; + } + ret = curr >= ends; + } while(0); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_feof(__stream); } - auto ret = ff_feof(reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p)=%i",__stream,ret); return ret; } __asm__(".symver feof,feof@GLIBC_2.2.5"); @@ -207,9 +209,13 @@ extern "C" int ferror(FILE * stream) __THROW { TRACE_SYSCALL(); - if(vfs::is_ff_handle(stream)) { - return vfs::vfs_is_initialized()?stdioGET_ERRNO():EIO; - } else { + if(is_filex(stream)) + { + auto fx = reinterpret_cast(stream); + return fx->error; + } + else + { return real_ferror(stream); } } @@ -217,16 +223,18 @@ extern "C" int fflush(FILE *__stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fflush(__stream); + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + ret = invoke_fs(&purefs::fs::filesystem::fsync, fx->fd); + fx->error = errno; } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_fflush(__stream); } - auto ret = ff_fflush(reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p)=%i",__stream,ret); return ret; } __asm__(".symver fflush,fflush@GLIBC_2.2.5"); @@ -234,95 +242,120 @@ extern "C" int fgetc(FILE *__stream) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fgetc(__stream); + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + char ch; + auto ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1); + fx->error = errno; + return ret; } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + return real_fgetc(__stream); } - auto ret = ff_fgetc(reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fgetc,fgetc@GLIBC_2.2.5"); int fgetpos(FILE *__restrict __stream, fpos_t *__restrict __pos) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fgetpos(__stream, __pos); - } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - auto ret = ff_ftell(reinterpret_cast(__stream)); - if (ret > 0 && __pos) { - __pos->__pos = ret; - return 0; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + auto ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR); + fx->error = errno; + if(__pos) { + __pos->__pos = ret; + } + return (ret>=0)?(0):(-1); } else - return ret; + { + return real_fgetpos(__stream, __pos); + } } __asm__(".symver fgetpos,fgetpos@GLIBC_2.2.5"); int fgetpos64(FILE *__restrict __stream, fpos64_t *__restrict __pos) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fgetpos64(__stream,__pos); - } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - auto ret = ff_ftell(reinterpret_cast(__stream)); - if (ret > 0 && __pos) { - __pos->__pos = ret; - return 0; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + auto ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR); + fx->error = errno; + if(__pos) { + __pos->__pos = ret; + } + return (ret>=0)?(0):(-1); } else - return ret; + { + return real_fgetpos64(__stream, __pos); + } } __asm__(".symver fgetpos64,fgetpos64@GLIBC_2.2.5"); char *fgets(char *__restrict __s, int __n, FILE *__restrict __stream) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fgets(__s,__n,__stream); + if(is_filex(__s)) + { + auto fx = reinterpret_cast(__stream); + char ch; + size_t pos = 0; + do { + auto ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1); + if(ret == 0) + { + fx->error = 0; + return nullptr; + } + else if(ret<0) + { + fx->error = errno; + return nullptr; + } else { + __s[pos++] = ch; + } + } while(ch == '\n'); + return __s; } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return nullptr; + else + { + return real_fgets(__s,__n,__stream); } - auto ret = ff_fgets(__s, __n, reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fgets,fgets@GLIBC_2.2.5"); int fileno(FILE *__stream) __THROW { - auto ret = vfsn::linux::internal::ff_file_to_fd(reinterpret_cast(__stream)); - if(ret<0) { - return real_fileno(__stream); - } else { - TRACE_SYSCALL(); - return ret; + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + ret = native_fd_to_image_fd(fx->fd); } + else + { + ret = real_fileno(__stream); + } + TRACE_SYSCALLN("(%p)=%i",__stream,ret); + return ret; } __asm__(".symver fileno,fileno@GLIBC_2.2.5"); int fprintf(FILE *__restrict __stream, const char *__restrict __format, ...) { + constexpr auto buf_len = 4096; int iCount; size_t xResult; char *pcBuffer; va_list xArgs; - if(!vfs::is_ff_handle(__stream)) { + if(!is_filex(__stream)) + { va_list arglist; va_start( arglist, __format ); auto ret = real_vfprintf( __stream, __format, arglist ); @@ -330,85 +363,95 @@ extern "C" return ret; } TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - pcBuffer = (char *)ffconfigMALLOC(ffconfigFPRINTF_BUFFER_LENGTH); + pcBuffer = new char[buf_len]; + auto fx = reinterpret_cast(__stream); if (pcBuffer == NULL) { /* Store the errno to thread local storage. */ - stdioSET_ERRNO(pdFREERTOS_ERRNO_ENOMEM); + fx->error = ENOMEM; iCount = -1; } else { va_start(xArgs, __format); - iCount = vsnprintf(pcBuffer, ffconfigFPRINTF_BUFFER_LENGTH, __format, xArgs); + iCount = vsnprintf(pcBuffer, buf_len, __format, xArgs); va_end(xArgs); /* ff_fwrite() will set ff_errno. */ if (iCount > 0) { - xResult = ff_fwrite(pcBuffer, (size_t)1, (size_t)iCount, reinterpret_cast(__stream)); + xResult = invoke_fs(&purefs::fs::filesystem::write, fx->fd, pcBuffer, iCount); if (xResult < (size_t)iCount) { iCount = -1; } } - ffconfigFREE(pcBuffer); + delete [] pcBuffer; } - errno = stdioGET_ERRNO(); + fx->error = errno; return iCount; } __asm__(".symver fprintf,fprintf@GLIBC_2.2.5"); int fputc(int __c, FILE *__stream) { - if(!vfs::is_ff_handle(__stream)) { + if(!is_filex(__stream)) + { return real_fputc( __c, __stream ); } - TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + TRACE_SYSCALL(); + auto fx = reinterpret_cast(__stream); + char ch = __c; + int ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, &ch, sizeof ch); + fx->error = errno; + return ret==1?0:ret; } - real_fprintf(stderr,"PUTC FILE %p\n", __stream ); - auto ret = ff_fputc(__c, reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fputc,fputc@GLIBC_2.2.5"); int fputs(const char *__restrict __s, FILE *__restrict __stream) { - if(!vfs::is_ff_handle(__stream)) { - return real_fputs( __s, __stream ); - } - TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + const auto len = strlen(__s); + ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, __s, len); + fx->error = errno; + ret = ret==int(len)?0:-1; } - int ret{-1}; - while (*__s) { - ret = ff_fputc(*__s++, reinterpret_cast(__stream)); - if (ret < 0) - break; + else + { + ret = real_fputs( __s, __stream ); } - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%s, %p)=%i",__s, __stream, ret); return ret; } __asm__(".symver fputs,fputs@GLIBC_2.2.5"); size_t fread(void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fread(__ptr,__size,__n,__stream); - } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + size_t ret {}; + if(__size!=0 && __n!=0) + { + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + char* p = reinterpret_cast(__ptr); + do { + auto res = invoke_fs(&purefs::fs::filesystem::read, fx->fd, p, __size); + const auto eof = res>0 && size_t(res)<__size; + fx->error = errno; + if(res<0 || eof) break; + p += __size; + --__n; + ++ret; + } while(__n > 0 ); + } + else + { + ret = real_fread(__ptr,__size,__n,__stream); + } } - auto ret = ff_fread(__ptr, __size, __n, reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p, %lu, %lu, %p)=%i",__ptr,__size,__n,__stream, ret); return ret; } __asm__(".symver fread,fread@GLIBC_2.2.5"); @@ -419,36 +462,33 @@ extern "C" FILE *__restrict __stream) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - auto ret = real_freopen(__filename,__modes,__stream); - real_fprintf(stderr, - "WARNING: redirecting freopen(%s,%s,%p) to the Linux fs. Native FILE*: %p\n", - __filename, __modes,__stream, ret); - return ret; - } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return nullptr; + if(!is_filex(__filename)) + { + return real_freopen(__filename,__modes,__stream); } - if( fclose(__stream) < 0) { - return nullptr; + else { + if( fclose(__stream) < 0) { + return nullptr; + } + return fopen(__filename, __modes ); } - return fopen(__filename, __modes ); } __asm__(".symver freopen,freopen@GLIBC_2.2.5"); int fseek (FILE *__stream, long int __off, int __whence) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_fseek(__stream,__off,__whence); + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __off, __whence); + ret = ret>0?0:ret; } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_fseek(__stream,__off,__whence); } - auto ret = ff_fseek(reinterpret_cast(__stream), __off, __whence ); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p, %li, %i)=%i",__stream,__off,__whence,ret); return ret; } __asm__(".symver fseek,fseek@GLIBC_2.2.5"); @@ -456,48 +496,48 @@ extern "C" int fsetpos (FILE *__stream, const fpos_t *__pos) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { + if(!is_filex(__stream)) + { return real_fsetpos(__stream,__pos); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + auto fx = reinterpret_cast(__stream); + auto ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __pos->__pos, SEEK_SET); + return ret>0?0:ret; } - auto ret = ff_fseek( reinterpret_cast(__stream), __pos->__pos, SEEK_SET ); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fsetpos,fsetpos@GLIBC_2.2.5"); int fsetpos64 (FILE *__stream, const fpos64_t *__pos) { TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { + if(!is_filex(__stream)) { return real_fsetpos64(__stream,__pos); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + auto fx = reinterpret_cast(__stream); + auto ret = invoke_fs(&purefs::fs::filesystem::seek, fx->fd, __pos->__pos, SEEK_SET); + return ret>0?0:ret; } - auto ret = ff_fseek( reinterpret_cast(__stream), __pos->__pos, SEEK_SET ); - errno = stdioGET_ERRNO(); - return ret; } __asm__(".symver fsetpos64,fsetpos64@GLIBC_2.2.5"); long int ftell (FILE *__stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_ftell(__stream); + long int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + ret = invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_CUR); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_ftell(__stream); } - auto ret = ff_ftell(reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p)=%i",__stream, ret); return ret; } __asm__(".symver ftell,ftell@GLIBC_2.2.5"); @@ -505,79 +545,107 @@ extern "C" size_t fwrite (const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s) { - if(!vfs::is_ff_handle(__s)) { - return real_fwrite( __ptr, __size, __n, __s ); - } - TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + int ret {}; + if(__size != 0 && __n != 0) + { + if(is_filex(__s)) + { + auto fx = reinterpret_cast(__s); + const char* p = reinterpret_cast(__ptr); + size_t items {}; + do { + auto ret = invoke_fs(&purefs::fs::filesystem::write, fx->fd, p, __size); + const auto eof = ret>=0 && size_t(ret)!=__size; + fx->error = errno; + if(ret<0 || eof) return ret; + p += __size; + --__n; + ++items; + } while(__n > 0 ); + ret = ret<0?(-1):(items); + } + else + { + ret = real_fwrite( __ptr, __size, __n, __s ); + } } - auto ret = ff_fwrite(__ptr, __size, __n, reinterpret_cast(__s)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(ptr: %p,size: %lu, n: %lu, fil: %p)=%i",__ptr,__size,__n,__s,ret); return ret; } __asm__(".symver fwrite,fwrite@GLIBC_2.2.5"); int getc(FILE *__stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_getc(__stream); + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + char ch; + ret = invoke_fs(&purefs::fs::filesystem::read,fx->fd,&ch,1); + fx->error = errno; + ret = (ret==1)?(ch):(ret); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_getc(__stream); } - auto ret = ff_fgetc(reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%p)=%i",__stream, ret); return ret; } __asm__(".symver getc,getc@GLIBC_2.2.5"); int putc(int __c, FILE *__stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - return real_putc(__c,__stream); + int ret {}; + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + char ch = __c; + ret = invoke_fs(&purefs::fs::filesystem::write,fx->fd, &ch, sizeof ch); + fx->error = errno; + ret = (ret==1)?(__c):(EOF); } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; + else + { + ret = real_fputc( __c, __stream ); } - auto ret = ff_fputc(__c, reinterpret_cast(__stream)); - errno = stdioGET_ERRNO(); + TRACE_SYSCALLN("(%i %p)=%i",__c,__stream, ret); return ret; } __asm__(".symver putc,putc@GLIBC_2.2.5"); int remove (const char *__filename) __THROW { - TRACE_SYSCALL(); - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return -1; - } - char namebuf[ffconfigMAX_FILENAME]; - auto ret = ff_remove(vfs::relative_to_root(namebuf,sizeof namebuf, __filename)); - if (ret && stdioGET_ERRNO() == EISDIR) - ret = ff_deltree(vfs::relative_to_root(namebuf,sizeof namebuf,__filename), nullptr, nullptr); - errno = stdioGET_ERRNO(); + int ret {}; + if(redirect_to_image(__filename)) + { + ret = invoke_fs(&purefs::fs::filesystem::unlink, __filename); + } + else + { + char tmp[PATH_MAX]; + const auto npath = npath_translate(__filename,tmp); + auto r_remove = reinterpret_cast(dlsym(RTLD_NEXT,"remove")); + ret = r_remove(npath); + } + TRACE_SYSCALLN("(%s)=%i",__filename, ret); return ret; } __asm__(".symver remove,remove@GLIBC_2.2.5"); void rewind (FILE *__stream) { - TRACE_SYSCALL(); - if(!vfs::is_ff_handle(__stream)) { - real_rewind(__stream); + TRACE_SYSCALLN("(%p)",__stream); + if(is_filex(__stream)) + { + auto fx = reinterpret_cast(__stream); + invoke_fs(&purefs::fs::filesystem::seek,fx->fd,0,SEEK_SET); + fx->error = errno; } - if(!vfs::vfs_is_initialized()) { - errno = EIO; - return; + else + { + real_rewind(__stream); } - ff_fseek(reinterpret_cast(__stream), 0L, SEEK_SET); } __asm__(".symver rewind,rewind@GLIBC_2.2.5"); @@ -620,4 +688,3 @@ extern "C" __asm__(".symver setlinebuf,setlinebuf@GLIBC_2.2.5"); } -#pragma GCC diagnostic pop diff --git a/module-services/service-fileindexer/ServiceFileIndexer.cpp b/module-services/service-fileindexer/ServiceFileIndexer.cpp index 72380524efecf7f16b8dd4bf1107f9b0d93761c6..ef6df449aeb088ef94e035794e628e0a48e23789 100644 --- a/module-services/service-fileindexer/ServiceFileIndexer.cpp +++ b/module-services/service-fileindexer/ServiceFileIndexer.cpp @@ -55,6 +55,7 @@ namespace service // Initialize data notification handler sys::ReturnCodes ServiceFileIndexer::InitHandler() { + /* vfs.registerNotificationHandler( [_this = shared_from_this()](std::string_view new_path, vfs::FsEvent event, std::string_view old_path) { namespace fs = std::filesystem; @@ -63,12 +64,15 @@ namespace service sys::Bus::SendUnicast(msg, std::string(service::name::file_indexer), _this.get()); }); mStartupIndexer.start(shared_from_this(), service::name::file_indexer); + */ return sys::ReturnCodes::Success; } sys::ReturnCodes ServiceFileIndexer::DeinitHandler() { + /* vfs.registerNotificationHandler(nullptr); + */ return sys::ReturnCodes::Success; } diff --git a/module-services/service-fileindexer/StartupIndexer.cpp b/module-services/service-fileindexer/StartupIndexer.cpp index ead3de7319af9bc6c0b06ad8131930de04ee17e4..441f00010db0996938df1b096048601d8d38a3cf 100644 --- a/module-services/service-fileindexer/StartupIndexer.cpp +++ b/module-services/service-fileindexer/StartupIndexer.cpp @@ -4,7 +4,7 @@ #include "StartupIndexer.hpp" #include "messages/FileChangeMessage.hpp" #include -#include +//#include #include #include #include "Constants.hpp" @@ -37,6 +37,7 @@ namespace service::detail // Collect startup files when service starts auto StartupIndexer::collectStartupFiles() -> void { + /* using namespace std::string_literals; auto searcher_cb = [](void *ctx, const char *path, bool isDir) { auto _this = reinterpret_cast(ctx); @@ -53,6 +54,7 @@ namespace service::detail for (const auto &path : start_dirs) { ff_stdio_listdir_recursive(path.c_str(), searcher_cb, this); } + */ } // Setup timers for notification auto StartupIndexer::setupTimers(std::shared_ptr svc, std::string_view svc_name) -> void diff --git a/module-utils/parallel-hashmap b/module-utils/parallel-hashmap new file mode 160000 index 0000000000000000000000000000000000000000..e77a448e95643a4cf9a0efdaa8fe91d44d97869c --- /dev/null +++ b/module-utils/parallel-hashmap @@ -0,0 +1 @@ +Subproject commit e77a448e95643a4cf9a0efdaa8fe91d44d97869c diff --git a/module-utils/test/unittest_utils.cpp b/module-utils/test/unittest_utils.cpp index 77b476c33850a718741492bff316ab61cdc6c3ca..43a505566b2332bbaa6081a1ad084d6434490672 100644 --- a/module-utils/test/unittest_utils.cpp +++ b/module-utils/test/unittest_utils.cpp @@ -305,7 +305,7 @@ class ScopedDir TEST_CASE("Read file length") { - ScopedDir dir(USER_PATH("test")); + ScopedDir dir("mytest"); auto *file = std::fopen(dir("test.txt").c_str(), "w"); REQUIRE(file != nullptr); std::array v = {42, -1, 7}; diff --git a/module-vfs/CMakeLists.txt b/module-vfs/CMakeLists.txt index a0418182df48395ffae5c652481124a6d015a73f..fe1732de874e8f263d0e2de3676558e9e46f3cc6 100644 --- a/module-vfs/CMakeLists.txt +++ b/module-vfs/CMakeLists.txt @@ -1,36 +1,15 @@ cmake_minimum_required(VERSION 3.12) -include(thirdparty) - project(module-vfs VERSION 1.0 DESCRIPTION "VFS module library") add_subdirectory(thirdparty/lfsfs) -set(FREERTOS_FAT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_crc.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_dir.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_error.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_fat.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_file.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_format.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_ioman.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_locking.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_memory.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_stdio.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_string.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_sys.c - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_time.c - ) - -third_party_source_optimization(${FREERTOS_FAT_SOURCES}) - set(FF_FAT_SOURCES_THIRDPARTY ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source/ff.c ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source/ffunicode.c ) -third_party_source_optimization(${FREERTOS_FAT_SOURCES_THIRDPARTY}) set(FF_FAT_SOURCES ${FF_FAT_SOURCES_THIRDPARTY} @@ -39,29 +18,7 @@ set(FF_FAT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/drivers/src/thirdparty/littlefs/lfs_glue.cpp ) - -# Disable some warnings due to ugly embedded hacks -# in the FREERTOS FAT implementation -if(${PROJECT_TARGET} STREQUAL "TARGET_Linux") -set_property(SOURCE ${FREERTOS_FAT_SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS -" -Wno-overflow -Wno-type-limits -Wno-format -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-stringop-truncation") -endif() - -set(PROJECT_INCLUDES - ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/include - ${CMAKE_CURRENT_SOURCE_DIR}/board/free_rtos_custom/include - ${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/include -) - -set(FREERTOS_FAT_EXTSOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/src/ff_stdio_flush.c - ${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/src/ff_file_flush.c - ${CMAKE_CURRENT_SOURCE_DIR}/freertos-fat-custom/src/ff_stdio_listdir_recursive.c -) - -set(SOURCES "" - ${FREERTOS_FAT_SOURCES} - ${FREERTOS_FAT_EXTSOURCES} +set(SOURCES ${FF_FAT_SOURCES} src/purefs/filesystem_paths.cpp src/purefs/blkdev/disk_manager.cpp @@ -76,12 +33,8 @@ set(SOURCES "" drivers/src/purefs/fs/filesystem_vfat.cpp drivers/src/purefs/fs/filesystem_littlefs.cpp src/deprecated/vfs.cpp - src/deprecated/vfsNotifier.cpp ) -if(NOT ${PROJECT_TARGET} STREQUAL "TARGET_Linux") - include(targets/Target_Cross.cmake) -endif() if(${PROJECT_TARGET} STREQUAL "TARGET_RT1051") include(targets/Target_RT1051.cmake) diff --git a/module-vfs/board/cross/free_rtos_custom/include/ff_eMMC_user_disk.hpp b/module-vfs/board/cross/free_rtos_custom/include/ff_eMMC_user_disk.hpp deleted file mode 100644 index 5696bd0b51c7598c3bbb2915132f5b437b13db5f..0000000000000000000000000000000000000000 --- a/module-vfs/board/cross/free_rtos_custom/include/ff_eMMC_user_disk.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#ifndef FREERTOS_PLUS_FAT_PORTABLE_FF_EMMC_USER_DISK_H_ -#define FREERTOS_PLUS_FAT_PORTABLE_FF_EMMC_USER_DISK_H_ - -#include "vfs.hpp" -#include "board/cross/eMMC/eMMC.hpp" - -FF_Disk_t *FF_eMMC_user_DiskInit(const char *pcName, bsp::eMMC *emmc); -BaseType_t FF_eMMC_user_DiskDelete(FF_Disk_t *pxDisk); -BaseType_t FF_eMMC_user_DiskShowPartition(FF_Disk_t *pxDisk); -void FF_eMMC_user_DiskFlush(FF_Disk_t *pxDisk); -uint8_t FF_eMMC_user_DiskIsPresent(void); - -#endif /* FREERTOS_PLUS_FAT_PORTABLE_FF_EMMC_USER_DISK_H_ */ diff --git a/module-vfs/board/cross/free_rtos_custom/portable/common.cpp b/module-vfs/board/cross/free_rtos_custom/portable/common.cpp deleted file mode 100644 index 239022f4e864e5be5ad064ecf36136b16369fab2..0000000000000000000000000000000000000000 --- a/module-vfs/board/cross/free_rtos_custom/portable/common.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -/* - * common.c - * - * Created on: 2 Feb 2018 - * Author: mati - */ -#include -#include -#include -#include