vfs.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. #include "c_stdlib.h"
  2. #include "c_stdio.h"
  3. #include "vfs.h"
  4. #define LDRV_TRAVERSAL 0
  5. // ---------------------------------------------------------------------------
  6. // RTC system interface
  7. //
  8. static sint32_t (*rtc_cb)( vfs_time *tm ) = NULL;
  9. // called by operating system
  10. void vfs_register_rtc_cb( sint32_t (*cb)( vfs_time *tm ) )
  11. {
  12. // allow NULL pointer to unregister callback function
  13. rtc_cb = cb;
  14. }
  15. // called by file system drivers
  16. sint32_t vfs_get_rtc( vfs_time *tm )
  17. {
  18. if (rtc_cb) {
  19. return rtc_cb( tm );
  20. }
  21. return VFS_RES_ERR;
  22. }
  23. static int dir_level = 1;
  24. static const char *normalize_path( const char *path )
  25. {
  26. #if ! LDRV_TRAVERSAL
  27. return path;
  28. #else
  29. const char *temp = path;
  30. size_t len;
  31. while ((len = c_strlen( temp )) >= 2) {
  32. if (temp[0] == '.' && temp[1] == '.') {
  33. --dir_level;
  34. if (len >= 4 && dir_level > 0) {
  35. // prepare next step
  36. temp = &(temp[4]);
  37. } else {
  38. // we're at top, the remainder is expected be an absolute path
  39. temp = &(temp[3]);
  40. }
  41. } else {
  42. break;
  43. }
  44. }
  45. if (dir_level > 0) {
  46. // no traversal on root level
  47. return path;
  48. } else {
  49. // path traverses via root
  50. return temp;
  51. }
  52. #endif
  53. }
  54. // ---------------------------------------------------------------------------
  55. // file system functions
  56. //
  57. vfs_vol *vfs_mount( const char *name, int num )
  58. {
  59. vfs_fs_fns *fs_fns;
  60. const char *normname = normalize_path( name );
  61. char *outname;
  62. #ifdef BUILD_SPIFFS
  63. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  64. return fs_fns->mount( outname, num );
  65. }
  66. #endif
  67. #ifdef BUILD_FATFS
  68. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  69. vfs_vol *r = fs_fns->mount( outname, num );
  70. c_free( outname );
  71. return r;
  72. }
  73. #endif
  74. return NULL;
  75. }
  76. int vfs_open( const char *name, const char *mode )
  77. {
  78. vfs_fs_fns *fs_fns;
  79. const char *normname = normalize_path( name );
  80. char *outname;
  81. #ifdef BUILD_SPIFFS
  82. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  83. return (int)fs_fns->open( outname, mode );
  84. }
  85. #endif
  86. #ifdef BUILD_FATFS
  87. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  88. int r = (int)fs_fns->open( outname, mode );
  89. c_free( outname );
  90. return r;
  91. }
  92. #endif
  93. return 0;
  94. }
  95. vfs_dir *vfs_opendir( const char *name )
  96. {
  97. vfs_fs_fns *fs_fns;
  98. const char *normname = normalize_path( name );
  99. char *outname;
  100. #ifdef BUILD_SPIFFS
  101. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  102. return fs_fns->opendir( outname );
  103. }
  104. #endif
  105. #ifdef BUILD_FATFS
  106. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  107. vfs_dir *r = fs_fns->opendir( outname );
  108. c_free( outname );
  109. return r;
  110. }
  111. #endif
  112. return NULL;
  113. }
  114. sint32_t vfs_stat( const char *name, struct vfs_stat *buf )
  115. {
  116. vfs_fs_fns *fs_fns;
  117. const char *normname = normalize_path( name );
  118. char *outname;
  119. #ifdef BUILD_SPIFFS
  120. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  121. return fs_fns->stat( outname, buf );
  122. }
  123. #endif
  124. #ifdef BUILD_FATFS
  125. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  126. sint32_t r = fs_fns->stat( outname, buf );
  127. c_free( outname );
  128. return r;
  129. }
  130. #endif
  131. return VFS_RES_ERR;
  132. }
  133. sint32_t vfs_remove( const char *name )
  134. {
  135. vfs_fs_fns *fs_fns;
  136. const char *normname = normalize_path( name );
  137. char *outname;
  138. #ifdef BUILD_SPIFFS
  139. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  140. return fs_fns->remove( outname );
  141. }
  142. #endif
  143. #ifdef BUILD_FATFS
  144. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  145. sint32_t r = fs_fns->remove( outname );
  146. c_free( outname );
  147. return r;
  148. }
  149. #endif
  150. return VFS_RES_ERR;
  151. }
  152. sint32_t vfs_rename( const char *oldname, const char *newname )
  153. {
  154. vfs_fs_fns *fs_fns;
  155. const char *normoldname = normalize_path( oldname );
  156. const char *normnewname = normalize_path( newname );
  157. char *oldoutname, *newoutname;
  158. #ifdef BUILD_SPIFFS
  159. if (myspiffs_realm( normoldname, &oldoutname, FALSE )) {
  160. if (fs_fns = myspiffs_realm( normnewname, &newoutname, FALSE )) {
  161. return fs_fns->rename( oldoutname, newoutname );
  162. }
  163. }
  164. #endif
  165. #ifdef BUILD_FATFS
  166. if (myfatfs_realm( normoldname, &oldoutname, FALSE )) {
  167. if (fs_fns = myfatfs_realm( normnewname, &newoutname, FALSE )) {
  168. sint32_t r = fs_fns->rename( oldoutname, newoutname );
  169. c_free( oldoutname );
  170. c_free( newoutname );
  171. return r;
  172. }
  173. c_free( oldoutname );
  174. }
  175. #endif
  176. return -1;
  177. }
  178. sint32_t vfs_mkdir( const char *name )
  179. {
  180. vfs_fs_fns *fs_fns;
  181. const char *normname = normalize_path( name );
  182. char *outname;
  183. #ifdef BUILD_SPIFFS
  184. // not supported
  185. #endif
  186. #ifdef BUILD_FATFS
  187. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  188. sint32_t r = fs_fns->mkdir( outname );
  189. c_free( outname );
  190. return r;
  191. }
  192. #endif
  193. return VFS_RES_ERR;
  194. }
  195. sint32_t vfs_fsinfo( const char *name, uint32_t *total, uint32_t *used )
  196. {
  197. vfs_fs_fns *fs_fns;
  198. char *outname;
  199. if (!name) name = ""; // current drive
  200. const char *normname = normalize_path( name );
  201. #ifdef BUILD_SPIFFS
  202. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  203. return fs_fns->fsinfo( total, used );
  204. }
  205. #endif
  206. #ifdef BUILD_FATFS
  207. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  208. c_free( outname );
  209. return fs_fns->fsinfo( total, used );
  210. }
  211. #endif
  212. return VFS_RES_ERR;
  213. }
  214. sint32_t vfs_fscfg( const char *name, uint32_t *phys_addr, uint32_t *phys_size)
  215. {
  216. vfs_fs_fns *fs_fns;
  217. char *outname;
  218. #ifdef BUILD_SPIFFS
  219. if (fs_fns = myspiffs_realm( "/FLASH", &outname, FALSE )) {
  220. return fs_fns->fscfg( phys_addr, phys_size );
  221. }
  222. #endif
  223. #ifdef BUILD_FATFS
  224. // not supported
  225. #endif
  226. // Error
  227. return VFS_RES_ERR;
  228. }
  229. sint32_t vfs_format( void )
  230. {
  231. vfs_fs_fns *fs_fns;
  232. char *outname;
  233. #ifdef BUILD_SPIFFS
  234. if (fs_fns = myspiffs_realm( "/FLASH", &outname, FALSE )) {
  235. return fs_fns->format();
  236. }
  237. #endif
  238. #ifdef BUILD_FATFS
  239. // not supported
  240. #endif
  241. // Error
  242. return 0;
  243. }
  244. sint32_t vfs_chdir( const char *path )
  245. {
  246. vfs_fs_fns *fs_fns;
  247. const char *normpath = normalize_path( path );
  248. const char *level;
  249. char *outname;
  250. int ok = VFS_RES_ERR;
  251. #if LDRV_TRAVERSAL
  252. // track dir level
  253. if (normpath[0] == '/') {
  254. dir_level = 0;
  255. level = &(normpath[1]);
  256. } else {
  257. level = normpath;
  258. }
  259. while (c_strlen( level ) > 0) {
  260. dir_level++;
  261. if (level = c_strchr( level, '/' )) {
  262. level++;
  263. } else {
  264. break;
  265. }
  266. }
  267. #endif
  268. #ifdef BUILD_SPIFFS
  269. if (fs_fns = myspiffs_realm( normpath, &outname, TRUE )) {
  270. // our SPIFFS integration doesn't support directories
  271. if (c_strlen( outname ) == 0) {
  272. ok = VFS_RES_OK;
  273. }
  274. }
  275. #endif
  276. #ifdef BUILD_FATFS
  277. if (fs_fns = myfatfs_realm( normpath, &outname, TRUE )) {
  278. if (c_strchr( outname, ':' )) {
  279. // need to set FatFS' default drive
  280. fs_fns->chdrive( outname );
  281. // and force chdir to root in case path points only to root
  282. fs_fns->chdir( "/" );
  283. }
  284. if (fs_fns->chdir( outname ) == VFS_RES_OK) {
  285. ok = VFS_RES_OK;
  286. }
  287. c_free( outname );
  288. }
  289. #endif
  290. return ok == VFS_RES_OK ? VFS_RES_OK : VFS_RES_ERR;
  291. }
  292. sint32_t vfs_errno( const char *name )
  293. {
  294. vfs_fs_fns *fs_fns;
  295. char *outname;
  296. if (!name) name = ""; // current drive
  297. const char *normname = normalize_path( name );
  298. #ifdef BUILD_SPIFFS
  299. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  300. return fs_fns->ferrno( );
  301. }
  302. #endif
  303. #ifdef BUILD_FATFS
  304. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  305. sint32_t r = fs_fns->ferrno( );
  306. c_free( outname );
  307. return r;
  308. }
  309. #endif
  310. return VFS_RES_ERR;
  311. }
  312. sint32_t vfs_ferrno( int fd )
  313. {
  314. vfs_file *f = (vfs_file *)fd;
  315. if (f) {
  316. return f->fns->ferrno ? f->fns->ferrno( f ) : 0;
  317. } else {
  318. vfs_fs_fns *fs_fns;
  319. const char *name = ""; // current drive
  320. char *outname;
  321. #ifdef BUILD_SPIFFS
  322. if (fs_fns = myspiffs_realm( name, &outname, FALSE )) {
  323. return fs_fns->ferrno( );
  324. }
  325. #endif
  326. #ifdef BUILD_FATFS
  327. if (fs_fns = myfatfs_realm( name, &outname, FALSE )) {
  328. sint32_t r = fs_fns->ferrno( );
  329. c_free( outname );
  330. return r;
  331. }
  332. #endif
  333. }
  334. }
  335. void vfs_clearerr( const char *name )
  336. {
  337. vfs_fs_fns *fs_fns;
  338. char *outname;
  339. if (!name) name = ""; // current drive
  340. const char *normname = normalize_path( name );
  341. #ifdef BUILD_SPIFFS
  342. if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
  343. fs_fns->clearerr( );
  344. }
  345. #endif
  346. #ifdef BUILD_FATFS
  347. if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
  348. fs_fns->clearerr( );
  349. c_free( outname );
  350. }
  351. #endif
  352. }
  353. const char *vfs_basename( const char *path )
  354. {
  355. const char *basename;
  356. // deduce basename (incl. extension) for length check
  357. if (basename = c_strrchr( path, '/' )) {
  358. basename++;
  359. } else if (basename = c_strrchr( path, ':' )) {
  360. basename++;
  361. } else {
  362. basename = path;
  363. }
  364. return basename;
  365. }
  366. // ---------------------------------------------------------------------------
  367. // supplementary functions
  368. //
  369. int vfs_getc( int fd )
  370. {
  371. unsigned char c = 0xFF;
  372. sint32_t res;
  373. if(!vfs_eof( fd )) {
  374. if (1 != vfs_read( fd, &c, 1 )) {
  375. NODE_DBG("getc errno %i\n", vfs_ferrno( fd ));
  376. return VFS_EOF;
  377. } else {
  378. return (int)c;
  379. }
  380. }
  381. return VFS_EOF;
  382. }
  383. int vfs_ungetc( int c, int fd )
  384. {
  385. return vfs_lseek( fd, -1, VFS_SEEK_CUR );
  386. }