vfs.c 9.2 KB

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