luat_fs_lfs2.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #include "luat_base.h"
  2. #include "luat_fs.h"
  3. #include "luat_spi.h"
  4. #include "luat_malloc.h"
  5. #define LUAT_LOG_TAG "vfs.lfs2"
  6. #include "luat_log.h"
  7. #ifdef LUAT_USE_FS_VFS
  8. // #ifdef LUAT_VFS_USE_LFS2
  9. #include "lfs.h"
  10. FILE* luat_vfs_lfs2_fopen(void* userdata, const char *filename, const char *mode) {
  11. lfs_t* fs = (lfs_t*)userdata;
  12. lfs_file_t *file = (lfs_file_t*)luat_heap_malloc(sizeof(lfs_file_t));
  13. int flag = 0;
  14. /*
  15. "r": 读模式(默认);
  16. "w": 写模式;
  17. "a": 追加模式;
  18. "r+": 更新模式,所有之前的数据都保留;
  19. "w+": 更新模式,所有之前的数据都删除;
  20. "a+": 追加更新模式,所有之前的数据都保留,只允许在文件尾部做写入。
  21. */
  22. if (!strcmp("r+", mode) || !strcmp("r+b", mode)) {
  23. flag = LFS_O_RDWR | LFS_O_CREAT;
  24. }
  25. else if(!strcmp("w+", mode) || !strcmp("w+b", mode)) {
  26. flag = LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC;
  27. }
  28. else if(!strcmp("a+", mode) || !strcmp("a+b", mode)) {
  29. flag = LFS_O_APPEND | LFS_O_CREAT;
  30. }
  31. else if(!strcmp("w", mode) || !strcmp("wb", mode)) {
  32. flag = LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC;
  33. }
  34. else if(!strcmp("r", mode) || !strcmp("rb", mode)) {
  35. flag = LFS_O_RDONLY;
  36. }
  37. else if(!strcmp("a", mode) || !strcmp("ab", mode)) {
  38. flag = LFS_O_APPEND | LFS_O_CREAT;
  39. }
  40. else {
  41. LLOGW("bad file open mode %s, fallback to 'r'", mode);
  42. flag = LFS_O_RDONLY;
  43. }
  44. int ret = lfs_file_open(fs, file, filename, flag);
  45. if (ret < 0) {
  46. luat_heap_free(file);
  47. return 0;
  48. }
  49. return (FILE*)file;
  50. }
  51. int luat_vfs_lfs2_getc(void* userdata, FILE* stream) {
  52. //LLOGD("posix_getc %p", stream);
  53. lfs_t* fs = (lfs_t*)userdata;
  54. lfs_file_t* file = (lfs_file_t*)stream;
  55. char buff = 0;
  56. int ret = lfs_file_read(fs, file, &buff, 1);
  57. if (ret < 0)
  58. return -1;
  59. return (int)buff;
  60. }
  61. int luat_vfs_lfs2_fseek(void* userdata, FILE* stream, long int offset, int origin) {
  62. lfs_t* fs = (lfs_t*)userdata;
  63. lfs_file_t* file = (lfs_file_t*)stream;
  64. int ret = lfs_file_seek(fs, file, offset, origin);
  65. return ret < 0 ? -1 : 0;
  66. }
  67. int luat_vfs_lfs2_ftell(void* userdata, FILE* stream) {
  68. lfs_t* fs = (lfs_t*)userdata;
  69. lfs_file_t* file = (lfs_file_t*)stream;
  70. int ret = lfs_file_tell(fs, file);
  71. return ret < 0 ? -1 : ret;
  72. }
  73. int luat_vfs_lfs2_fclose(void* userdata, FILE* stream) {
  74. lfs_t* fs = (lfs_t*)userdata;
  75. lfs_file_t* file = (lfs_file_t*)stream;
  76. lfs_file_close(fs, file);
  77. if (file != NULL)
  78. luat_heap_free(file);
  79. return 0;
  80. }
  81. int luat_vfs_lfs2_feof(void* userdata, FILE* stream) {
  82. lfs_t* fs = (lfs_t*)userdata;
  83. lfs_file_t* file = (lfs_file_t*)stream;
  84. if (lfs_file_size(fs, file) <= lfs_file_tell(fs, file))
  85. return 1;
  86. return 0;
  87. }
  88. int luat_vfs_lfs2_ferror(void* userdata, FILE *stream) {
  89. return 0;
  90. }
  91. size_t luat_vfs_lfs2_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream) {
  92. lfs_t* fs = (lfs_t*)userdata;
  93. lfs_file_t* file = (lfs_file_t*)stream;
  94. int ret = lfs_file_read(fs, file, ptr, size*nmemb);
  95. return ret < 0 ? 0 : ret;
  96. }
  97. size_t luat_vfs_lfs2_fwrite(void* userdata, const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  98. lfs_t* fs = (lfs_t*)userdata;
  99. lfs_file_t* file = (lfs_file_t*)stream;
  100. int ret = lfs_file_write(fs, file, ptr, size*nmemb);
  101. return ret < 0 ? 0 : ret;
  102. }
  103. int luat_vfs_lfs2_remove(void* userdata, const char *filename) {
  104. lfs_t* fs = (lfs_t*)userdata;
  105. return lfs_remove(fs, filename);
  106. }
  107. int luat_vfs_lfs2_rename(void* userdata, const char *old_filename, const char *new_filename) {
  108. lfs_t* fs = (lfs_t*)userdata;
  109. return lfs_rename(fs, old_filename, new_filename);
  110. }
  111. int luat_vfs_lfs2_fexist(void* userdata, const char *filename) {
  112. FILE* fd = luat_vfs_lfs2_fopen(userdata, filename, "rb");
  113. if (fd) {
  114. luat_vfs_lfs2_fclose(userdata, fd);
  115. return 1;
  116. }
  117. return 0;
  118. }
  119. size_t luat_vfs_lfs2_fsize(void* userdata, const char *filename) {
  120. FILE *fd;
  121. size_t size = 0;
  122. fd = luat_vfs_lfs2_fopen(userdata, filename, "rb");
  123. if (fd) {
  124. size = lfs_file_size((lfs_t*)userdata, (lfs_file_t*)fd);
  125. luat_vfs_lfs2_fclose(userdata, fd);
  126. }
  127. return size;
  128. }
  129. int luat_vfs_lfs2_mkfs(void* userdata, luat_fs_conf_t *conf) {
  130. int ret = 0;
  131. lfs_t* fs = (lfs_t*)userdata;
  132. if (fs != NULL && fs->cfg != NULL) {
  133. ret = lfs_format(fs, fs->cfg);
  134. // LLOGD("lfs2 format ret %d", ret);
  135. if (ret < 0)
  136. return ret;
  137. ret = lfs_mount(fs, fs->cfg);
  138. // LLOGD("lfs2 mount ret %d", ret);
  139. return ret;
  140. }
  141. return -1;
  142. }
  143. int luat_vfs_lfs2_mount(void** userdata, luat_fs_conf_t *conf) {
  144. *userdata = (void*)conf->busname;
  145. return 0;
  146. }
  147. int luat_vfs_lfs2_umount(void* userdata, luat_fs_conf_t *conf) {
  148. LLOGE("not support yet : umount");
  149. return 0;
  150. }
  151. int luat_vfs_lfs2_mkdir(void* userdata, char const* _DirName) {
  152. return -1;
  153. }
  154. int luat_vfs_lfs2_rmdir(void* userdata, char const* _DirName) {
  155. return -1;
  156. }
  157. int luat_vfs_lfs2_lsdir(void* userdata, char const* _DirName, luat_fs_dirent_t* ents, size_t offset, size_t len) {
  158. lfs_t* fs = (lfs_t*)userdata;
  159. int ret , num = 0;
  160. lfs_dir_t *dir;
  161. struct lfs_info info;
  162. // if (fs->filecount > offset) {
  163. // if (offset + len > fs->filecount)
  164. // len = fs->filecount - offset;
  165. dir = luat_heap_malloc(sizeof(lfs_dir_t));
  166. if (dir == NULL) {
  167. // LLOGE("out of memory when lsdir");
  168. return 0;
  169. }
  170. ret = lfs_dir_open(fs, dir, _DirName);
  171. if (ret < 0) {
  172. luat_heap_free(dir);
  173. // LLOGE("no such dir %s _DirName");
  174. return 0;
  175. }
  176. // TODO 使用seek/tell组合更快更省
  177. for (size_t i = 0; i < offset; i++)
  178. {
  179. ret = lfs_dir_read(fs, dir, &info);
  180. if (ret <= 0) {
  181. lfs_dir_close(fs, dir);
  182. luat_heap_free(dir);
  183. return 0;
  184. }
  185. }
  186. for (size_t i = 0; i < len; i++)
  187. {
  188. ret = lfs_dir_read(fs, dir, &info);
  189. if (ret < 0) {
  190. lfs_dir_close(fs, dir);
  191. luat_heap_free(dir);
  192. return 0;
  193. }
  194. if (ret == 0) {
  195. len = i;
  196. break;
  197. }
  198. if (info.type == 2 && (memcmp(info.name, ".", 2) !=0 ||memcmp(info.name, "..", 3)!=0))
  199. continue;
  200. ents[num].d_type = info.type - 1; // lfs file =1, dir=2
  201. strcpy(ents[num].d_name, info.name);
  202. num++;
  203. }
  204. lfs_dir_close(fs, dir);
  205. luat_heap_free(dir);
  206. return num;
  207. // }
  208. return 0;
  209. }
  210. int luat_vfs_lfs2_info(void* userdata, const char* path, luat_fs_info_t *conf) {
  211. lfs_t* fs = (lfs_t*)userdata;
  212. memcpy(conf->filesystem, "lfs", strlen("lfs")+1);
  213. conf->type = 0;
  214. conf->total_block = fs->cfg->block_count;
  215. conf->block_used = lfs_fs_size(fs);
  216. conf->block_size = fs->cfg->block_size;
  217. return 0;
  218. }
  219. #define T(name) .name = luat_vfs_lfs2_##name
  220. const struct luat_vfs_filesystem vfs_fs_lfs2 = {
  221. .name = "lfs2",
  222. .opts = {
  223. T(mkfs),
  224. T(mount),
  225. T(umount),
  226. T(mkdir),
  227. T(rmdir),
  228. T(lsdir),
  229. T(remove),
  230. T(rename),
  231. T(fsize),
  232. T(fexist),
  233. T(info)
  234. },
  235. .fopts = {
  236. T(fopen),
  237. T(getc),
  238. T(fseek),
  239. T(ftell),
  240. T(fclose),
  241. T(feof),
  242. T(ferror),
  243. T(fread),
  244. T(fwrite)
  245. }
  246. };
  247. // #endif
  248. #endif