123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include "vfs.h"
- #include "vfs_int.h"
- #define LDRV_TRAVERSAL 0
- // This interferes with our clearerr member in our ops struct
- #undef clearerr
- // ---------------------------------------------------------------------------
- // RTC system interface
- //
- static int32_t (*rtc_cb)( vfs_time *tm ) = NULL;
- // called by operating system
- void vfs_register_rtc_cb( int32_t (*cb)( vfs_time *tm ) )
- {
- // allow NULL pointer to unregister callback function
- rtc_cb = cb;
- }
- // called by file system drivers
- int32_t vfs_get_rtc( vfs_time *tm )
- {
- if (rtc_cb) {
- return rtc_cb( tm );
- }
- return VFS_RES_ERR;
- }
- static int dir_level = 1;
- #if ! LDRV_TRAVERSAL
- #define normalize_path(p) (p)
- #else
- static const char *normalize_path( const char *path )
- {
- const char *temp = path;
- size_t len;
- while ((len = strlen( temp )) >= 2) {
- if (temp[0] == '.' && temp[1] == '.') {
- --dir_level;
- if (len >= 4 && dir_level > 0) {
- // prepare next step
- temp = &(temp[4]);
- } else {
- // we're at top, the remainder is expected be an absolute path
- temp = &(temp[3]);
- }
- } else {
- break;
- }
- }
- if (dir_level > 0) {
- // no traversal on root level
- return path;
- } else {
- // path traverses via root
- return temp;
- }
- }
- #endif
- // ---------------------------------------------------------------------------
- // file system functions
- //
- vfs_vol *vfs_mount( const char *name, int num )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->mount( outname, num );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- vfs_vol *r = fs_fns->mount( outname, num );
- free( outname );
- return r;
- }
- #endif
- return NULL;
- }
- int vfs_open( const char *name, const char *mode )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return (int)fs_fns->open( outname, mode );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- int r = (int)fs_fns->open( outname, mode );
- free( outname );
- return r;
- }
- #endif
- return 0;
- }
- vfs_dir *vfs_opendir( const char *name )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->opendir( outname );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- vfs_dir *r = fs_fns->opendir( outname );
- free( outname );
- return r;
- }
- #endif
- return NULL;
- }
- int32_t vfs_stat( const char *name, struct vfs_stat *buf )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->stat( outname, buf );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- int32_t r = fs_fns->stat( outname, buf );
- free( outname );
- return r;
- }
- #endif
- return VFS_RES_ERR;
- }
- int32_t vfs_remove( const char *name )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->remove( outname );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- int32_t r = fs_fns->remove( outname );
- free( outname );
- return r;
- }
- #endif
- return VFS_RES_ERR;
- }
- int32_t vfs_rename( const char *oldname, const char *newname )
- {
- vfs_fs_fns *fs_fns;
- const char *normoldname = normalize_path( oldname );
- const char *normnewname = normalize_path( newname );
- char *oldoutname, *newoutname;
- #ifdef BUILD_SPIFFS
- if (myspiffs_realm( normoldname, &oldoutname, FALSE )) {
- if (fs_fns = myspiffs_realm( normnewname, &newoutname, FALSE )) {
- return fs_fns->rename( oldoutname, newoutname );
- }
- }
- #endif
- #ifdef BUILD_FATFS
- if (myfatfs_realm( normoldname, &oldoutname, FALSE )) {
- if (fs_fns = myfatfs_realm( normnewname, &newoutname, FALSE )) {
- int32_t r = fs_fns->rename( oldoutname, newoutname );
- free( oldoutname );
- free( newoutname );
- return r;
- }
- free( oldoutname );
- }
- #endif
- return -1;
- }
- int32_t vfs_mkdir( const char *name )
- {
- vfs_fs_fns *fs_fns;
- const char *normname = normalize_path( name );
- char *outname;
- #ifdef BUILD_SPIFFS
- // not supported
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- int32_t r = fs_fns->mkdir( outname );
- free( outname );
- return r;
- }
- #endif
- return VFS_RES_ERR;
- }
- int32_t vfs_fsinfo( const char *name, uint32_t *total, uint32_t *used )
- {
- vfs_fs_fns *fs_fns;
- char *outname;
- if (!name) name = ""; // current drive
- const char *normname = normalize_path( name );
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->fsinfo( total, used );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- free( outname );
- return fs_fns->fsinfo( total, used );
- }
- #endif
- return VFS_RES_ERR;
- }
- int32_t vfs_fscfg( const char *name, uint32_t *phys_addr, uint32_t *phys_size)
- {
- vfs_fs_fns *fs_fns;
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( "/FLASH", &outname, FALSE )) {
- return fs_fns->fscfg( phys_addr, phys_size );
- }
- #endif
- #ifdef BUILD_FATFS
- // not supported
- #endif
- // Error
- return VFS_RES_ERR;
- }
- int32_t vfs_format( void )
- {
- vfs_fs_fns *fs_fns;
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( "/FLASH", &outname, FALSE )) {
- return fs_fns->format();
- }
- #endif
- #ifdef BUILD_FATFS
- // not supported
- #endif
- // Error
- return 0;
- }
- int32_t vfs_chdir( const char *path )
- {
- vfs_fs_fns *fs_fns;
- const char *normpath = normalize_path( path );
- const char *level;
- char *outname;
- int ok = VFS_RES_ERR;
- #if LDRV_TRAVERSAL
- // track dir level
- if (normpath[0] == '/') {
- dir_level = 0;
- level = &(normpath[1]);
- } else {
- level = normpath;
- }
- while (strlen( level ) > 0) {
- dir_level++;
- if (level = strchr( level, '/' )) {
- level++;
- } else {
- break;
- }
- }
- #endif
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normpath, &outname, TRUE )) {
- // our SPIFFS integration doesn't support directories
- if (strlen( outname ) == 0) {
- ok = VFS_RES_OK;
- }
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normpath, &outname, TRUE )) {
- if (strchr( outname, ':' )) {
- // need to set FatFS' default drive
- fs_fns->chdrive( outname );
- // and force chdir to root in case path points only to root
- fs_fns->chdir( "/" );
- }
- if (fs_fns->chdir( outname ) == VFS_RES_OK) {
- ok = VFS_RES_OK;
- }
- free( outname );
- }
- #endif
- return ok == VFS_RES_OK ? VFS_RES_OK : VFS_RES_ERR;
- }
- int32_t vfs_errno( const char *name )
- {
- vfs_fs_fns *fs_fns;
- char *outname;
- if (!name) name = ""; // current drive
- const char *normname = normalize_path( name );
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- return fs_fns->ferrno( );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- int32_t r = fs_fns->ferrno( );
- free( outname );
- return r;
- }
- #endif
- return VFS_RES_ERR;
- }
- int32_t vfs_ferrno( int fd )
- {
- vfs_file *f = (vfs_file *)fd;
- if (f) {
- return f->fns->ferrno ? f->fns->ferrno( f ) : 0;
- } else {
- vfs_fs_fns *fs_fns;
- const char *name = ""; // current drive
- char *outname;
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( name, &outname, FALSE )) {
- return fs_fns->ferrno( );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( name, &outname, FALSE )) {
- int32_t r = fs_fns->ferrno( );
- free( outname );
- return r;
- }
- #endif
- }
- }
- void vfs_clearerr( const char *name )
- {
- vfs_fs_fns *fs_fns;
- char *outname;
- if (!name) name = ""; // current drive
- const char *normname = normalize_path( name );
- #ifdef BUILD_SPIFFS
- if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
- fs_fns->clearerr ( );
- }
- #endif
- #ifdef BUILD_FATFS
- if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
- fs_fns->clearerr ( );
- free( outname );
- }
- #endif
- }
- const char *vfs_basename( const char *path )
- {
- const char *basename;
- // deduce basename (incl. extension) for length check
- if (basename = strrchr( path, '/' )) {
- basename++;
- } else if (basename = strrchr( path, ':' )) {
- basename++;
- } else {
- basename = path;
- }
- return basename;
- }
- // ---------------------------------------------------------------------------
- // supplementary functions
- //
- int vfs_getc( int fd )
- {
- unsigned char c = 0xFF;
- int32_t res;
- if(!vfs_eof( fd )) {
- if (1 != vfs_read( fd, &c, 1 )) {
- NODE_DBG("getc errno %i\n", vfs_ferrno( fd ));
- return VFS_EOF;
- } else {
- return (int)c;
- }
- }
- return VFS_EOF;
- }
- int vfs_ungetc( int c, int fd )
- {
- return vfs_lseek( fd, -1, VFS_SEEK_CUR );
- }
|