From 43b9c4572486c82608be256693361a5e5250b1e5 Mon Sep 17 00:00:00 2001 From: Lucjan Bryndza Date: Thu, 26 Nov 2020 13:29:36 +0100 Subject: [PATCH] [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 --- .../linux/libiosyscalls/include/internal.hpp | 1 + board/linux/libiosyscalls/src/dirent.cpp | 31 +++++- .../libiosyscalls/src/syscalls_posix.cpp | 67 +++++++++++-- .../src/syscalls_scan_family.cpp | 11 ++- .../libiosyscalls/src/syscalls_stdio.cpp | 93 +++++++++++++++++- .../cross/free_rtos_custom/portable/vfs.cpp | 1 + .../linux/free_rtos_custom/portable/vfs.cpp | 5 + module-vfs/include/user/deprecated/vfs.hpp | 6 ++ module-vfs/src/deprecated/vfs.cpp | 95 ++++++++++++++++++- module-vfs/src/newlib/vfs_io_syscalls.cpp | 80 ++++++++++++++++ 10 files changed, 375 insertions(+), 15 deletions(-) diff --git a/board/linux/libiosyscalls/include/internal.hpp b/board/linux/libiosyscalls/include/internal.hpp index 58ac9f613e3a1a196c293b02905b3e9c2df4971d..d109e1cce548cddb7761e43512662ac1499b352a 100644 --- a/board/linux/libiosyscalls/include/internal.hpp +++ b/board/linux/libiosyscalls/include/internal.hpp @@ -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(); } diff --git a/board/linux/libiosyscalls/src/dirent.cpp b/board/linux/libiosyscalls/src/dirent.cpp index ccd42c6fef07b1ac8e43608333dc3f56a4c8a247..e994e7f5cdaa0c90c309e077eb66d08810b3886f 100644 --- a/board/linux/libiosyscalls/src/dirent.cpp +++ b/board/linux/libiosyscalls/src/dirent.cpp @@ -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(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(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"); diff --git a/board/linux/libiosyscalls/src/syscalls_posix.cpp b/board/linux/libiosyscalls/src/syscalls_posix.cpp index b2a2f7397e7648dad4147cb60d09b94fcb5595eb..070eca5eb9e0b6a0b13eb057805cfb8cfc233092 100644 --- a/board/linux/libiosyscalls/src/syscalls_posix.cpp +++ b/board/linux/libiosyscalls/src/syscalls_posix.cpp @@ -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); diff --git a/board/linux/libiosyscalls/src/syscalls_scan_family.cpp b/board/linux/libiosyscalls/src/syscalls_scan_family.cpp index b17307055549a99d65670a26876cf8f35955b58f..4dd8d1eee9aa441d20f703c1c49fd50e5e0cfc0c 100644 --- a/board/linux/libiosyscalls/src/syscalls_scan_family.cpp +++ b/board/linux/libiosyscalls/src/syscalls_scan_family.cpp @@ -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(__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; diff --git a/board/linux/libiosyscalls/src/syscalls_stdio.cpp b/board/linux/libiosyscalls/src/syscalls_stdio.cpp index e596d465a4b7ea591b4ebac2300d7f1638a2e33c..7dd296d3f3aef0daf31b5fed80f43b0ab37bab9b 100644 --- a/board/linux/libiosyscalls/src/syscalls_stdio.cpp +++ b/board/linux/libiosyscalls/src/syscalls_stdio.cpp @@ -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 _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(__stream)); { std::lock_guard _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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__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(__stream), 0L, SEEK_SET); } __asm__(".symver rewind,rewind@GLIBC_2.2.5"); diff --git a/module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp b/module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp index 9f1ac70f08e9c68f8903b910180959bf5a789632..ba652830f490bfd3180f78a61a4c749e7595c0d7 100644 --- a/module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp +++ b/module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp @@ -49,4 +49,5 @@ void vfs::Init() LOG_INFO("vfs::Init looks like %s exists", userDiskPath.c_str()); } chnNotifier.onFileSystemInitialized(); + initDone = true; } diff --git a/module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp b/module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp index c310a2dc4afcdb85408cc4fa945f585e0d7420ca..a041041b8ca3a94b84ce382e791473f0a5113030 100644 --- a/module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp +++ b/module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp @@ -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 diff --git a/module-vfs/include/user/deprecated/vfs.hpp b/module-vfs/include/user/deprecated/vfs.hpp index aa18cbe43a450e1f76bc13fee8cbd7eb1b4bb3b7..556a07d86e14524c5c61b4b91149f6b4bc988d4b 100644 --- a/module-vfs/include/user/deprecated/vfs.hpp +++ b/module-vfs/include/user/deprecated/vfs.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #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 initDone; }; extern vfs vfs; diff --git a/module-vfs/src/deprecated/vfs.cpp b/module-vfs/src/deprecated/vfs.cpp index 415b825c9b00fe48f90c3792ec7ac1398d54dd03..118f309bbfee2e0b17f697f69fc38d67899cbe97 100644 --- a/module-vfs/src/deprecated/vfs.cpp +++ b/module-vfs/src/deprecated/vfs.cpp @@ -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 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::listdir(const char *path, const std::string &ext, const bool bypassRootCheck) { + if (!initDone) { + stdioSET_ERRNO(pdFREERTOS_ERRNO_EIO); + return {}; + } std::vector dir_list; FileAttributes attribute; @@ -147,12 +196,19 @@ std::vector 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(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]; diff --git a/module-vfs/src/newlib/vfs_io_syscalls.cpp b/module-vfs/src/newlib/vfs_io_syscalls.cpp index 025ea626aabe1e8f66f8940d74baeea4c4531e31..99e7be1c004d9c5908f35ab5eb16de4c3774299b 100644 --- a/module-vfs/src/newlib/vfs_io_syscalls.cpp +++ b/module-vfs/src/newlib/vfs_io_syscalls.cpp @@ -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(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(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);