luat_fs_fatfs.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "luat_base.h"
  2. #include "luat_fs.h"
  3. #include "luat_mem.h"
  4. #define LUAT_LOG_TAG "fatfs"
  5. #include "luat_log.h"
  6. #if defined(LUAT_USE_FS_VFS) && defined(LUAT_USE_FATFS)
  7. #include "ff.h"
  8. #include "diskio.h"
  9. FILE* luat_vfs_fatfs_fopen(void* userdata, const char *filename, const char *mode) {
  10. //LLOGD("f_open %s %s", filename, mode);
  11. //FATFS *fs = (FATFS*)userdata;
  12. FIL* fp = luat_heap_malloc(sizeof(FIL));
  13. int flag = 0;
  14. if (!strcmp("r+", mode) || !strcmp("r+b", mode) || !strcmp("rb+", mode)) {
  15. flag = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
  16. }
  17. else if(!strcmp("w+", mode) || !strcmp("w+b", mode) || !strcmp("wb+", mode)) {
  18. flag = FA_READ | FA_WRITE | FA_CREATE_ALWAYS;
  19. }
  20. else if(!strcmp("a+", mode) || !strcmp("a+b", mode) || !strcmp("ab+", mode)) {
  21. flag = FA_READ | FA_WRITE | FA_OPEN_APPEND;
  22. }
  23. else if(!strcmp("w", mode) || !strcmp("wb", mode)) {
  24. flag = FA_WRITE | FA_READ;
  25. }
  26. else if(!strcmp("r", mode) || !strcmp("rb", mode)) {
  27. flag = FA_READ;
  28. }
  29. else if(!strcmp("a", mode) || !strcmp("ab", mode)) {
  30. flag = FA_WRITE | FA_OPEN_APPEND;
  31. }
  32. else {
  33. LLOGW("bad file open mode %s, fallback to 'r'", mode);
  34. flag = FA_READ;
  35. }
  36. FRESULT ret = f_open(fp, filename, flag);
  37. if (ret != FR_OK) {
  38. LLOGD("f_open %s %d", filename, ret);
  39. luat_heap_free(fp);
  40. return 0;
  41. }
  42. return (FILE*)fp;
  43. }
  44. int luat_vfs_fatfs_getc(void* userdata, FILE* stream) {
  45. //FATFS *fs = (FATFS*)userdata;
  46. FIL* fp = (FIL*)stream;
  47. char buff = 0;
  48. UINT result = 0;
  49. FRESULT ret = f_read(fp, (void*)&buff, 1, &result);
  50. if (ret == FR_OK && result == 1) {
  51. return buff;
  52. }
  53. return -1;
  54. }
  55. int luat_vfs_fatfs_fseek(void* userdata, FILE* stream, long int offset, int origin) {
  56. //FATFS *fs = (FATFS*)userdata;
  57. FIL* fp = (FIL*)stream;
  58. int npos = f_tell(fp);
  59. if (origin == SEEK_SET) {
  60. npos = offset;
  61. } else if (origin == SEEK_CUR) {
  62. npos += offset;
  63. } else if (origin == SEEK_END) {
  64. npos = f_size(fp);
  65. }
  66. FRESULT ret = f_lseek(fp, npos);
  67. if (ret == FR_OK) {
  68. return 0;
  69. }
  70. return -1;
  71. }
  72. int luat_vfs_fatfs_ftell(void* userdata, FILE* stream) {
  73. //FATFS *fs = (FATFS*)userdata;
  74. FIL* fp = (FIL*)stream;
  75. return f_tell(fp);
  76. }
  77. int luat_vfs_fatfs_fclose(void* userdata, FILE* stream) {
  78. //FATFS *fs = (FATFS*)userdata;
  79. FIL* fp = (FIL*)stream;
  80. if (fp != NULL) {
  81. f_close(fp);
  82. luat_heap_free(fp);
  83. }
  84. return 0;
  85. }
  86. int luat_vfs_fatfs_feof(void* userdata, FILE* stream) {
  87. //FATFS *fs = (FATFS*)userdata;
  88. FIL* fp = (FIL*)stream;
  89. return f_eof(fp);
  90. }
  91. int luat_vfs_fatfs_ferror(void* userdata, FILE *stream) {
  92. //FATFS *fs = (FATFS*)userdata;
  93. FIL* fp = (FIL*)stream;
  94. return f_error(fp);
  95. }
  96. size_t luat_vfs_fatfs_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream) {
  97. //FATFS *fs = (FATFS*)userdata;
  98. FIL* fp = (FIL*)stream;
  99. UINT result = 0;
  100. FRESULT ret = f_read(fp, ptr, size*nmemb, &result);
  101. if (ret == FR_OK) {
  102. return result;
  103. }
  104. return 0;
  105. }
  106. size_t luat_vfs_fatfs_fwrite(void* userdata, const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  107. //FATFS *fs = (FATFS*)userdata;
  108. FIL* fp = (FIL*)stream;
  109. UINT result = 0;
  110. FRESULT ret = f_write(fp, ptr, size*nmemb, &result);
  111. if (ret == FR_OK) {
  112. return result;
  113. }
  114. return 0;
  115. }
  116. int luat_vfs_fatfs_remove(void* userdata, const char *filename) {
  117. return f_unlink(filename);
  118. }
  119. int luat_vfs_fatfs_rename(void* userdata, const char *old_filename, const char *new_filename) {
  120. return f_rename(old_filename + (old_filename[0] == '/' ? 1 : 0), new_filename + (new_filename[0] == '/' ? 1 : 0));
  121. }
  122. int luat_vfs_fatfs_fexist(void* userdata, const char *filename) {
  123. FILINFO fno = {0};
  124. FRESULT ret = f_stat(filename, &fno);
  125. if (ret == FR_OK) {
  126. return 1;
  127. }
  128. return 0;
  129. }
  130. size_t luat_vfs_fatfs_fsize(void* userdata, const char *filename) {
  131. FILINFO fno = {0};
  132. FRESULT ret = f_stat(filename, &fno);
  133. if (ret == FR_OK) {
  134. return fno.fsize;
  135. }
  136. return 0;
  137. }
  138. int luat_vfs_fatfs_mkfs(void* userdata, luat_fs_conf_t *conf) {
  139. (void)userdata;
  140. (void)conf;
  141. MKFS_PARM parm = {
  142. .fmt = FM_ANY, // 暂时应付一下ramdisk
  143. .au_size = 0,
  144. .align = 0,
  145. .n_fat = 0,
  146. .n_root = 0,
  147. };
  148. BYTE work[FF_MAX_SS] = {0};
  149. int re = f_mkfs("/", &parm, work, FF_MAX_SS);
  150. LLOGD("format ret %d", re);
  151. return re;
  152. }
  153. int luat_vfs_fatfs_mount(void** userdata, luat_fs_conf_t *conf) {
  154. *userdata = (void*)conf->busname;
  155. return 0;
  156. }
  157. int luat_vfs_fatfs_umount(void* userdata, luat_fs_conf_t *conf) {
  158. //LLOGE("not support yet : umount");
  159. return 0;
  160. }
  161. int luat_vfs_fatfs_mkdir(void* userdata, char const* _DirName) {
  162. FRESULT ret = f_mkdir(_DirName);
  163. if (FR_OK == ret)
  164. return 0;
  165. LLOGD("mkdir ret %d", ret);
  166. return -1;
  167. }
  168. int luat_vfs_fatfs_rmdir(void* userdata, char const* _DirName) {
  169. FRESULT ret = f_rmdir(_DirName);
  170. if (FR_OK == ret)
  171. return 0;
  172. LLOGD("rmdir ret %d", ret);
  173. return -1;
  174. }
  175. int luat_vfs_fatfs_lsdir(void* userdata, char const* _DirName, luat_fs_dirent_t* ents, size_t offset, size_t len) {
  176. DIR dir = {0};
  177. FRESULT res = 0;
  178. FILINFO fno = {0};
  179. size_t i = 0;
  180. size_t count = 0;
  181. res = f_opendir(&dir, _DirName);
  182. if (res != FR_OK) {
  183. LLOGD("opendir %s %d", _DirName, res);
  184. return 0;
  185. }
  186. for (i = 0; i < offset; i++)
  187. {
  188. res = f_readdir(&dir, &fno);
  189. if (res != FR_OK || fno.fname[0] == 0) {
  190. return 0; // 读取失败或者是读完了
  191. };
  192. }
  193. for (i = 0; i < len; i++)
  194. {
  195. res = f_readdir(&dir, &fno);
  196. if (res != FR_OK || fno.fname[0] == 0) {
  197. break;
  198. };
  199. count ++;
  200. if (fno.fattrib & AM_DIR) {
  201. ents[i].d_type = 1;
  202. }
  203. else {
  204. ents[i].d_type = 0;
  205. }
  206. if (strlen(fno.fname) < 255)
  207. memcpy(&ents[i].d_name, fno.fname, strlen(fno.fname) + 1);
  208. else {
  209. memcpy(ents[i].d_name, fno.fname, 254);
  210. ents[i].d_name[254] = 0;
  211. }
  212. }
  213. return count;
  214. }
  215. int luat_vfs_fatfs_info(void* userdata, const char* path, luat_fs_info_t *conf) {
  216. // DWORD fre_clust = 0;
  217. // DWORD fre_sect = 0
  218. // DWORD tot_sect = 0;
  219. FATFS *fs = (FATFS*)userdata;
  220. // tot_sect = (fs->n_fatent - 2) * fs->csize;
  221. // fre_sect = (fs->free_clst) * fs->csize;
  222. memcpy(conf->filesystem, "fatfs", strlen("fatfs")+1);
  223. conf->type = 0;
  224. conf->total_block = (fs->n_fatent - 2) * fs->csize;
  225. conf->block_used = (fs->n_fatent - 2 - fs->free_clst) * fs->csize;
  226. conf->block_size = 512;
  227. return 0;
  228. }
  229. void* luat_vfs_fatfs_opendir(void* userdata, const char *_DirName) {
  230. DIR *dp = (DIR*)luat_heap_malloc(sizeof(DIR));
  231. if (dp == NULL) {
  232. LLOGD("out of memory when open file %s", dp);
  233. return NULL;
  234. }
  235. memset(dp, 0, sizeof(DIR));
  236. FRESULT ret = f_opendir(dp, _DirName);
  237. if (ret != FR_OK) {
  238. luat_heap_free(dp);
  239. return NULL;
  240. }
  241. return (void*)dp;
  242. }
  243. int luat_vfs_fatfs_closedir(void* userdata, void* dir) {
  244. DIR* dp = (DIR*)dir;
  245. f_closedir(dp);
  246. if (dp)luat_heap_free(dp);
  247. return 0;
  248. }
  249. #define T(name) .name = luat_vfs_fatfs_##name
  250. const struct luat_vfs_filesystem vfs_fs_fatfs = {
  251. .name = "fatfs",
  252. .opts = {
  253. T(mkfs),
  254. T(mount),
  255. T(umount),
  256. T(mkdir),
  257. T(rmdir),
  258. T(lsdir),
  259. T(remove),
  260. T(rename),
  261. T(fsize),
  262. T(fexist),
  263. T(info),
  264. T(opendir),
  265. T(closedir)
  266. },
  267. .fopts = {
  268. T(fopen),
  269. T(getc),
  270. T(fseek),
  271. T(ftell),
  272. T(fclose),
  273. T(feof),
  274. T(ferror),
  275. T(fread),
  276. T(fwrite)
  277. }
  278. };
  279. #endif