~aleteoryx/muditaos

43b9c4572486c82608be256693361a5e5250b1e5 — Lucjan Bryndza 5 years ago 46aa1ee
[EGD-4512] Prevent vfs crash before init (#1091)

Currently calling any method from class vfs
causes aplication crash when methods are called before
vfs.Init() call. This commit prevent to crash end return failure
instead. The fix is related to any any vfs methods and methods called
through the standard syscall.
It is only the hotfix and it will be removed when new VFS subsystem
will be ready.

Co-authored-by: Lucjan Bryndza <lucjan.bryndza@mudita.com>
M board/linux/libiosyscalls/include/internal.hpp => board/linux/libiosyscalls/include/internal.hpp +1 -0
@@ 13,4 13,5 @@ namespace vfsn::linux::internal
    _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();
}

M board/linux/libiosyscalls/src/dirent.cpp => board/linux/libiosyscalls/src/dirent.cpp +29 -2
@@ 24,15 24,18 @@ extern "C" {

    DIR *opendir(const char *dirname)
    {
        namespace vfs = vfsn::linux::internal;
        TRACE_SYSCALL();
        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, vfs::relative_to_root(dirbuf,sizeof dirbuf,dirname));
        dir->dir_data = diren::diropen(errno, relative_to_root(dirbuf,sizeof dirbuf,dirname));
        if (!dir->dir_data) {
            delete dir;
            return nullptr;


@@ 51,6 54,10 @@ extern "C" {
            errno = EBADF;
            return -1;
        }
        if(!vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto res = diren::dirclose(errno, dirp->dir_data);
        delete dirp;
        return res;


@@ 64,6 71,10 @@ extern "C" {
            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<FF_FindData_t *>(dirp->dir_data->dir_state);


@@ 93,6 104,10 @@ 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<FF_FindData_t *>(dirp->dir_data->dir_state);


@@ 123,6 138,10 @@ extern "C" {
            errno = EBADF;
            return;
        }
        if(!vfs_is_initialized()) {
            errno = EIO;
            return;
        }
        diren::dirreset(errno, dirp->dir_data);
        dirp->position = 0;
    }


@@ 135,6 154,10 @@ extern "C" {
            errno = EBADF;
            return;
        }
        if(!vfs_is_initialized()) {
            errno = EIO;
            return;
        }
        if (loc < 0) {
            return;
        }


@@ 155,6 178,10 @@ extern "C" {
            errno = EBADF;
            return -1;
        }
        if(!vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        return dirp->position;
    }
    __asm__(".symver telldir,telldir@GLIBC_2.2.5");

M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +61 -6
@@ 78,6 78,10 @@ extern "C" {
     int unlink(const char *name)
     {
        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, name));
        if (ret && stdioGET_ERRNO() == EISDIR)


@@ 89,7 93,12 @@ extern "C" {

    int stat(const char *file, struct stat *pstat) {
        TRACE_SYSCALL();
        auto ret = ff_cstat(file, pstat);
        int ret {};
        if(!vfs::vfs_is_initialized()) {
            ret = -1;
        } else {
            ret = ff_cstat(file, pstat);
        }
        if(ret) {
            real_fprintf(stderr,"WARNING: redirecting stat(%s) to the linux fs\n",file);
            ret = real_xstat(1,file,pstat);


@@ 101,7 110,12 @@ extern "C" {
    int fstat(int fd, struct stat *pstat)
    {
        TRACE_SYSCALL();
        FF_FILE* fil = vfsn::linux::internal::fd_to_ff_file(fd);
        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);


@@ 119,9 133,14 @@ extern "C" {
    int lstat(const char *pathname, struct stat *statbuf)
    {
        TRACE_SYSCALL();
        real_fprintf(stderr,"WARNING: redirecting lstat(%s) to the linux fs\n",pathname);
        auto ret = ff_cstat(pathname, statbuf);
        int ret;
        if(!vfs::vfs_is_initialized()) {
            ret = -1;
        } else {
            ret = ff_cstat(pathname, statbuf);
        }
        if(ret) {
            real_fprintf(stderr,"WARNING: redirecting lstat(%s) to the linux fs\n",pathname);
            ret = real_lxstat(1,pathname,statbuf);
        }
        return ret;


@@ 174,8 193,16 @@ extern "C" {
    {
        TRACE_SYSCALL();
        char pathbuf[ffconfigMAX_FILENAME];
        auto ret = ff_chdir(vfs::relative_to_root(pathbuf,sizeof pathbuf,path));
        errno  = stdioGET_ERRNO();
        int ret;
        if(!vfs::vfs_is_initialized())
        {
            ret = -1;
            errno = -EIO;
        }
        else {
            ret = ff_chdir(vfs::relative_to_root(pathbuf,sizeof pathbuf,path));
            errno  = stdioGET_ERRNO();
        }
        return ret;
    }
    __asm__(".symver chdir,chdir@GLIBC_2.2.5");


@@ 191,6 218,10 @@ extern "C" {
    char *getcwd(char *buf, size_t size)
    {
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return nullptr;
        }
        auto cwd = ff_getcwd(buf, size);
        errno  = stdioGET_ERRNO();
        return cwd;


@@ 200,6 231,10 @@ extern "C" {
    char *getwd(char *buf)
    {
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return nullptr;
        }
        auto cwd = ff_getcwd(buf, ffconfigMAX_FILENAME );
        errno  = stdioGET_ERRNO();
        return cwd;


@@ 210,6 245,10 @@ 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();


@@ 221,6 260,10 @@ extern "C" {
    int rename(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        char oldpbuf[ffconfigMAX_FILENAME];
        char newpbuf[ffconfigMAX_FILENAME];
        auto ret = ff_rename(vfs::relative_to_root(oldpbuf,sizeof oldpbuf, oldpath),


@@ 233,6 276,10 @@ extern "C" {
    int mkdir(const char *pathname, mode_t )
    {
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        char pathbuf[ffconfigMAX_FILENAME];
        auto ret = ff_mkdir(vfs::relative_to_root(pathbuf,sizeof pathbuf,pathname));
        errno  = stdioGET_ERRNO();


@@ 261,6 308,10 @@ extern "C" {
    int fsync(int fd)
    {
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto fil = vfsn::linux::internal::fd_to_ff_file(fd);
        if (!fil) {
            LOG_ERROR("Unable to find handle %i", fd);


@@ 329,6 380,10 @@ extern "C" {
            return real_xstat( ver,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);

M board/linux/libiosyscalls/src/syscalls_scan_family.cpp => board/linux/libiosyscalls/src/syscalls_scan_family.cpp +8 -3
@@ 89,6 89,10 @@ extern "C" {
            real_fprintf(stderr,"WARNING: redirecting ungetc(%p) to the linux fs\n",__stream);
            return real_ungetc(__c,__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        int ret = ff_fseek(reinterpret_cast<FF_FILE*>(__stream), -1, SEEK_CUR );
        if( ret ) {
            errno = stdioGET_ERRNO();


@@ 105,9 109,6 @@ extern "C" {
    }
    __asm__(".symver ungetc,vfscanf@GLIBC_2.2.5");




    int vfscanf (FILE *__restrict fp, const char *__restrict fmt,
                    __gnuc_va_list ap)
    {


@@ 116,6 117,10 @@ extern "C" {
            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;

M board/linux/libiosyscalls/src/syscalls_stdio.cpp => board/linux/libiosyscalls/src/syscalls_stdio.cpp +91 -2
@@ 124,7 124,12 @@ extern "C"
    {
        TRACE_SYSCALL();
        char pathbuf[ffconfigMAX_FILENAME];
        auto ret = ff_fopen(vfs::relative_to_root(pathbuf,sizeof pathbuf,pathname), mode);
        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<std::recursive_mutex> _lck(g_mutex);
            const auto fd = g_handles.insert(ret) + vfs::FIRST_FILEDESC;


@@ 156,6 161,10 @@ extern "C"
            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<FF_FILE *>(__stream));
        {
            std::lock_guard<std::recursive_mutex> _lck(g_mutex);


@@ 185,6 194,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_feof(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_feof(reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 195,7 208,7 @@ extern "C"
    {
        TRACE_SYSCALL();
        if(vfs::is_ff_handle(stream)) {
            return stdioGET_ERRNO();
            return vfs::vfs_is_initialized()?stdioGET_ERRNO():EIO;
        } else {
            return real_ferror(stream);
        }


@@ 208,6 221,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fflush(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fflush(reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 220,6 237,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fgetc(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fgetc(reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 232,6 253,10 @@ extern "C"
        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<FF_FILE *>(__stream));
        if (ret > 0 && __pos) {
            __pos->__pos = ret;


@@ 248,6 273,10 @@ extern "C"
        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<FF_FILE *>(__stream));
        if (ret > 0 && __pos) {
            __pos->__pos = ret;


@@ 264,6 293,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fgets(__s,__n,__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return nullptr;
        }
        auto ret = ff_fgets(__s, __n, reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 297,6 330,10 @@ extern "C"
            return ret;
        }
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        pcBuffer = (char *)ffconfigMALLOC(ffconfigFPRINTF_BUFFER_LENGTH);
        if (pcBuffer == NULL) {
            /* Store the errno to thread local storage. */


@@ 328,6 365,10 @@ extern "C"
            return real_fputc( __c, __stream );
        }
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        real_fprintf(stderr,"PUTC FILE %p\n", __stream );
        auto ret = ff_fputc(__c, reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();


@@ 341,6 382,10 @@ extern "C"
            return real_fputs( __s, __stream );
        }
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        int ret;
        while (*__s) {
            ret = ff_fputc(*__s++, reinterpret_cast<FF_FILE *>(__stream));


@@ 358,6 403,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fread(__ptr,__size,__n,__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fread(__ptr, __size, __n, reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 377,6 426,10 @@ extern "C"
                __filename, __modes,__stream, ret);
            return  ret;
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return nullptr;
        }
        if( fclose(__stream) < 0) {
            return nullptr;
        }


@@ 390,6 443,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fseek(__stream,__off,__whence);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fseek(reinterpret_cast<FF_FILE*>(__stream), __off, __whence );
        errno = stdioGET_ERRNO();
        return ret;


@@ 402,6 459,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fsetpos(__stream,__pos);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fseek( reinterpret_cast<FF_FILE*>(__stream), __pos->__pos, SEEK_SET );
        errno = stdioGET_ERRNO();
        return ret;


@@ 414,6 475,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_fsetpos64(__stream,__pos);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fseek( reinterpret_cast<FF_FILE*>(__stream), __pos->__pos, SEEK_SET );
        errno = stdioGET_ERRNO();
        return ret;


@@ 427,6 492,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_ftell(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_ftell(reinterpret_cast<FF_FILE*>(__stream));
        errno = stdioGET_ERRNO();
        return ret;


@@ 440,6 509,10 @@ extern "C"
            return real_fwrite( __ptr, __size, __n, __s );
        }
        TRACE_SYSCALL();
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fwrite(__ptr, __size, __n, reinterpret_cast<FF_FILE*>(__s));
        errno = stdioGET_ERRNO();
        return ret;


@@ 452,6 525,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_getc(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fgetc(reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 464,6 541,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            return real_putc(__c,__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return -1;
        }
        auto ret = ff_fputc(__c, reinterpret_cast<FF_FILE *>(__stream));
        errno    = stdioGET_ERRNO();
        return ret;


@@ 473,6 554,10 @@ extern "C"
    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)


@@ 488,6 573,10 @@ extern "C"
        if(!vfs::is_ff_handle(__stream)) {
            real_rewind(__stream);
        }
        if(!vfs::vfs_is_initialized()) {
            errno = EIO;
            return;
        }
        ff_fseek(reinterpret_cast<FF_FILE*>(__stream), 0L, SEEK_SET);
    }
    __asm__(".symver rewind,rewind@GLIBC_2.2.5");

M module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp => module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp +1 -0
@@ 49,4 49,5 @@ void vfs::Init()
        LOG_INFO("vfs::Init looks like %s exists", userDiskPath.c_str());
    }
    chnNotifier.onFileSystemInitialized();
    initDone = true;
}

M module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp => module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp +5 -0
@@ 22,6 22,10 @@ namespace vfsn::linux::internal
    {
        return std::strncpy(out_path, vfs.relativeToRoot(inpath).c_str(), out_path_len);
    }
    bool vfs_is_initialized()
    {
        return vfs.isInitialized();
    }
} // namespace vfsn::linux::internal

vfs::vfs()


@@ 69,5 73,6 @@ void vfs::Init()
        LOG_INFO("vfs::Init looks like %s exists", userDiskPath.c_str());
    }
    chnNotifier.onFileSystemInitialized();
    initDone = true;
}
#pragma GCC diagnostic pop

M module-vfs/include/user/deprecated/vfs.hpp => module-vfs/include/user/deprecated/vfs.hpp +6 -0
@@ 11,6 11,7 @@
#include <crc32/crc32.h>
#include <log/log.hpp>
#include <json/json11.hpp>
#include <atomic>
#include "vfsNotifier.hpp"
#include "vfs_globals.hpp"



@@ 160,6 161,10 @@ class vfs
    [[deprecated]] static bool verifyCRC(const std::string filePath, const unsigned long crc32);
    [[deprecated]] static bool verifyCRC(const fs::path filePath);
    [[deprecated]] static std::string generateRandomId(size_t length);
    auto isInitialized() const noexcept
    {
        return initDone.load();
    }

  private:
    bool updateFileCRC32(const fs::path &file);


@@ 168,6 173,7 @@ class vfs
    bool updateBootConfig(const fs::path &bootJsonPath);
    struct purefs::BootConfig bootConfig;
    vfsn::utility::vfsNotifier chnNotifier;
    static std::atomic<bool> initDone;
};

extern vfs vfs;

M module-vfs/src/deprecated/vfs.cpp => module-vfs/src/deprecated/vfs.cpp +93 -2
@@ 14,15 14,21 @@
#define eMMCSECTORS_PER_MB      (eMMCBYTES_PER_MB / 512ull)

/* Used as a magic number to indicate that an FF_Disk_t structure is a RAM
disk. */
   disk. */
#define eMMCSIGNATURE             0x61606362
#define mainIO_MANAGER_CACHE_SIZE (15UL * FSL_SDMMC_DEFAULT_BLOCK_SIZE)

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

std::atomic<bool> vfs::initDone{false};

vfs::FILE *vfs::fopen(const char *filename, const char *mode)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return nullptr;
    }
    const auto filename_rel = relativeToRoot(filename);
    const auto handle       = ff_fopen(filename_rel.c_str(), mode);
    chnNotifier.onFileOpen(filename_rel, mode, handle);


@@ 31,6 37,10 @@ vfs::FILE *vfs::fopen(const char *filename, const char *mode)

int vfs::fclose(FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    const auto ret = ff_fclose(stream);
    chnNotifier.onFileClose(stream);
    return ret;


@@ 38,6 48,10 @@ int vfs::fclose(FILE *stream)

int vfs::remove(const char *name)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    const auto abs_name = relativeToRoot(name);
    const auto ret      = ff_remove(abs_name.c_str());
    if (!ret)


@@ 47,41 61,72 @@ int vfs::remove(const char *name)

size_t vfs::fread(void *ptr, size_t size, size_t count, FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return ssize_t(-1);
    }
    return ff_fread(ptr, size, count, stream);
}

size_t vfs::fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return size_t(0);
    }
    return ff_fwrite(ptr, size, count, stream);
}

int vfs::fseek(FILE *stream, long int offset, int origin)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    return ff_fseek(stream, offset, origin);
}

long int vfs::ftell(FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    return ff_ftell(stream);
}

void vfs::rewind(FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
    }
    ff_rewind(stream);
}

size_t vfs::filelength(FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return 0;
    }
    return ff_filelength(stream);
}

char *vfs::fgets(char *buff, size_t count, FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return nullptr;
    }
    return ff_fgets(buff, count, stream);
}

std::string vfs::getcurrdir()
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return {};
    }
    char buff[64] = {};
    ff_getcwd(buff, sizeof buff);
    return std::string{buff};


@@ 99,6 144,10 @@ static inline bool hasEnding(std::string const &fullString, std::string const &e

std::vector<vfs::DirectoryEntry> vfs::listdir(const char *path, const std::string &ext, const bool bypassRootCheck)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return {};
    }
    std::vector<DirectoryEntry> dir_list;

    FileAttributes attribute;


@@ 147,12 196,19 @@ std::vector<vfs::DirectoryEntry> vfs::listdir(const char *path, const std::strin

bool vfs::eof(FILE *stream)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return true;
    }
    return ff_feof(stream);
}

std::string vfs::getline(FILE *stream, uint32_t length)
{

    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return {};
    }
    uint32_t currentPosition = ftell(stream);

    // allocate memory to read number of signs defined by length param. Size of buffer is increased by 1 to add string's


@@ 178,6 234,11 @@ std::string vfs::getline(FILE *stream, uint32_t length)

vfs::FilesystemStats vfs::getFilesystemStats()
{

    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return {};
    }
    FF_Error_t xError;
    uint64_t ullFreeSectors;
    uint32_t ulTotalSizeMB, ulFreeSizeMB;


@@ 242,6 303,10 @@ std::string vfs::relativeToRoot(const std::string path)

bool vfs::isDir(const char *path)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return false;
    }
    if (path == nullptr)
        return false;



@@ 258,6 323,11 @@ bool vfs::isDir(const char *path)

bool vfs::fileExists(const char *path)
{

    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return false;
    }
    if (path == nullptr)
        return false;



@@ 271,6 341,10 @@ bool vfs::fileExists(const char *path)

int vfs::deltree(const char *path)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    if (path != nullptr)
        return ff_deltree(
            relativeToRoot(path).c_str(),


@@ 285,6 359,10 @@ int vfs::deltree(const char *path)

int vfs::mkdir(const char *dir)
{
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    if (dir != nullptr)
        return ff_mkdir(relativeToRoot(dir).c_str());
    else


@@ 293,6 371,11 @@ int vfs::mkdir(const char *dir)

int vfs::rename(const char *oldname, const char *newname)
{

    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return -1;
    }
    if (oldname != nullptr && newname != nullptr) {
        const auto old_rel = relativeToRoot(oldname);
        const auto new_rel = relativeToRoot(newname);


@@ 317,6 400,10 @@ size_t vfs::fprintf(FILE *stream, const char *format, ...)
    char *buffer = nullptr;
    va_list args;

    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return 0;
    }
    buffer = static_cast<char *>(ffconfigMALLOC(ffconfigFPRINTF_BUFFER_LENGTH));
    if (buffer == nullptr) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_ENOMEM);


@@ 340,6 427,10 @@ size_t vfs::fprintf(FILE *stream, const char *format, ...)
auto vfs::getAbsolutePath(std::string_view path) const -> std::string
{
    namespace fs = std::filesystem;
    if (!initDone) {
        stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO);
        return {};
    }
    fs::path fs_path(path);
    if (fs_path.is_relative()) {
        char cwd_path[ffconfigMAX_FILENAME];

M module-vfs/src/newlib/vfs_io_syscalls.cpp => module-vfs/src/newlib/vfs_io_syscalls.cpp +80 -0
@@ 66,6 66,10 @@ namespace vfsn::internal::syscalls
{
    int open(int &_errno_, const char *file, int flags, int mode)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto fflags = open_to_fopen_flags(flags);
        if (*fflags == '\0') {
            _errno_ = EINVAL;


@@ 91,6 95,10 @@ namespace vfsn::internal::syscalls

    long close(int &_errno_, int fd)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto fil = gFileHandles.clearHandle(fd);
        if (!fil) {
            LOG_ERROR("Unable to find handle %i", fd);


@@ 104,6 112,10 @@ namespace vfsn::internal::syscalls

    long write(int &_errno_, int fd, const void *buf, size_t cnt)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        if (fd == STDERR_FILENO || fd == STDOUT_FILENO) {
            log_WriteToDevice((uint8_t *)buf, cnt);
            return cnt;


@@ 121,6 133,10 @@ namespace vfsn::internal::syscalls

    long read(int &_errno_, int fd, void *buf, size_t cnt)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto fil = gFileHandles[fd];
        if (!fil) {
            LOG_ERROR("Unable to find handle %i", fd);


@@ 154,6 170,10 @@ namespace vfsn::internal::syscalls
    }
    int fstat(int &_errno_, int fd, struct stat *pstat)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto fil = gFileHandles[fd];
        if (!fil) {
            LOG_ERROR("Unable to find handle %i", fd);


@@ 170,12 190,20 @@ namespace vfsn::internal::syscalls
    }
    int link(int &_errno_, const char *existing, const char *newLink)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        _errno_ = ENOSYS;
        LOG_ERROR("Syscall %s not supported", __PRETTY_FUNCTION__);
        return -1;
    }
    int unlink(int &_errno_, const char *name)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        const auto rel_name = vfs.relativeToRoot(name);
        auto ret            = ff_remove(rel_name.c_str());
        if (ret && stdioGET_ERRNO() == EISDIR)


@@ 192,6 220,10 @@ namespace vfsn::internal::syscalls
    }
    int stat(int &_errno_, const char *file, struct stat *pstat)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        FF_Stat_t stat_ff;
        auto ret = ff_stat(vfs.relativeToRoot(file).c_str(), &stat_ff);
        if (!ret) {


@@ 214,18 246,30 @@ namespace vfsn::internal::syscalls

    int chdir(int &_errno_, const char *path)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto ret = ff_chdir(vfs.relativeToRoot(path).c_str());
        _errno_  = stdioGET_ERRNO();
        return ret;
    }
    char *getcwd(int &_errno_, char *buf, size_t size)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return nullptr;
        }
        auto cwd = ff_getcwd(buf, size);
        _errno_  = stdioGET_ERRNO();
        return cwd;
    }
    int rename(int &_errno_, const char *oldName, const char *newName)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto ret = ff_rename(vfs.relativeToRoot(oldName).c_str(), vfs.relativeToRoot(newName).c_str(), true);
        _errno_  = stdioGET_ERRNO();
        return ret;


@@ 233,6 277,10 @@ namespace vfsn::internal::syscalls

    int mkdir(int &_errno_, const char *path, uint32_t mode)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto ret = ff_mkdir(vfs.relativeToRoot(path).c_str());
        _errno_  = stdioGET_ERRNO();
        return ret;


@@ 240,6 288,10 @@ namespace vfsn::internal::syscalls

    DIR *opendir(int &_errno_, const char *dirname)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return nullptr;
        }
        auto dir      = new DIR;
        dir->dir_data = dirent::diropen(_errno_, vfs.relativeToRoot(dirname).c_str());
        if (!dir->dir_data) {


@@ 254,6 306,10 @@ namespace vfsn::internal::syscalls

    int closedir(int &_errno_, DIR *dirp)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        if (!dirp) {
            _errno_ = EBADF;
            return -1;


@@ 269,6 325,10 @@ namespace vfsn::internal::syscalls
            _errno_ = EBADF;
            return nullptr;
        }
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return nullptr;
        }
        auto olderrno{_errno_};
        auto res = dirent::dirnext(_errno_, dirp->dir_data);
        auto fff = reinterpret_cast<FF_FindData_t *>(dirp->dir_data->dir_state);


@@ 294,6 354,10 @@ namespace vfsn::internal::syscalls
        if (!dirp) {
            return EBADF;
        }
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto olderrno{_errno_};
        auto res = dirent::dirnext(_errno_, dirp->dir_data);
        auto fff = reinterpret_cast<FF_FindData_t *>(dirp->dir_data->dir_state);


@@ 321,6 385,10 @@ namespace vfsn::internal::syscalls
        if (!dirp) {
            return;
        }
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return;
        }
        dirent::dirreset(_errno_, dirp->dir_data);
        dirp->position = 0;
    }


@@ 330,6 398,10 @@ namespace vfsn::internal::syscalls
        if (!dirp || loc < 0) {
            return;
        }
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return;
        }
        if (dirp->position > loc) {
            dirent::dirreset(_errno_, dirp->dir_data);
            dirp->position = 0;


@@ 343,6 415,10 @@ namespace vfsn::internal::syscalls
        if (!dirp) {
            return -1;
        }
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        return dirp->position;
    }



@@ 360,6 436,10 @@ namespace vfsn::internal::syscalls
    }
    int fsync(int &_errno_, int fd)
    {
        if (!vfs.isInitialized()) {
            _errno_ = EIO;
            return -1;
        }
        auto fil = gFileHandles[fd];
        if (!fil) {
            LOG_ERROR("Unable to find handle %i", fd);