luat_fs_mem.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. #include "luat_base.h"
  2. #include "luat_fs.h"
  3. #include "luat_mem.h"
  4. #define LUAT_LOG_TAG "fs"
  5. #include "luat_log.h"
  6. #if 1
  7. #define BLOCK_SIZE 4096
  8. typedef struct ram_file_block
  9. {
  10. uint8_t data[BLOCK_SIZE];
  11. struct ram_file_block* next;
  12. } ram_file_block_t;
  13. typedef struct ram_file
  14. {
  15. size_t size; // 当前文件大小
  16. char name[32]; // 文件名称
  17. ram_file_block_t* head; // 链表头指针
  18. } ram_file_t;
  19. typedef struct luat_ram_fd
  20. {
  21. int fid;
  22. uint32_t offset;
  23. uint8_t readonly;
  24. } luat_raw_fd_t;
  25. #define RAM_FILE_MAX (64)
  26. static ram_file_t* files[RAM_FILE_MAX];
  27. size_t luat_vfs_ram_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream);
  28. FILE* luat_vfs_ram_fopen(void* userdata, const char *filename, const char *mode) {
  29. (void)userdata;
  30. // LLOGD("ram fs open %s %s", filename, mode);
  31. if (filename == NULL || mode == NULL || strlen(filename) > 31)
  32. return NULL;
  33. // 读文件
  34. if (!strcmp("r", mode) || !strcmp("rb", mode)) {
  35. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  36. {
  37. if (files[i] == NULL)
  38. continue;
  39. if (!strcmp(files[i]->name, filename)) {
  40. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  41. if (fd == NULL) {
  42. LLOGE("out of memory when malloc luat_raw_fd_t");
  43. return NULL;
  44. }
  45. fd->fid = i;
  46. fd->offset = 0;
  47. fd->readonly = 1;
  48. return (FILE*)fd;
  49. }
  50. }
  51. return NULL;
  52. }
  53. // 写文件
  54. else if (!strcmp("w", mode) || !strcmp("wb", mode) || !strcmp("w+", mode) || !strcmp("wb+", mode) || !strcmp("w+b", mode) || !strcmp("r+", mode) || !strcmp("rb+", mode) || !strcmp("r+b", mode)) {
  55. // 先看看是否存在, 如果存在就重用老的
  56. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  57. {
  58. if (files[i] == NULL)
  59. continue;
  60. if (!strcmp(files[i]->name, filename)) {
  61. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  62. if (fd == NULL) {
  63. LLOGE("out of memory when malloc luat_raw_fd_t");
  64. return NULL;
  65. }
  66. fd->fid = i;
  67. fd->readonly = 0;
  68. fd->offset = 0;
  69. if (!strcmp("w+", mode) || !strcmp("wb+", mode) || !strcmp("w+b", mode)) {
  70. // 截断模式
  71. files[i]->size = 0;
  72. ram_file_block_t* block = files[i]->head;
  73. while (block) {
  74. ram_file_block_t* next = block->next;
  75. luat_heap_free(block);
  76. block = next;
  77. }
  78. files[i]->head = NULL;
  79. }
  80. return (FILE*)fd;
  81. }
  82. }
  83. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  84. {
  85. if (files[i] != NULL)
  86. continue;
  87. ram_file_t *file = luat_heap_malloc(sizeof(ram_file_t));
  88. if (file == NULL) {
  89. LLOGE("out of memory when malloc ram_file_t");
  90. return NULL;
  91. }
  92. memset(file, 0, sizeof(ram_file_t));
  93. strcpy(file->name, filename);
  94. files[i] = file;
  95. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  96. if (fd == NULL) {
  97. LLOGE("out of memory when malloc luat_raw_fd_t");
  98. return NULL;
  99. }
  100. fd->fid = i;
  101. fd->offset = 0;
  102. fd->readonly = 0;
  103. return (FILE*)fd;
  104. }
  105. }
  106. // 追加模式
  107. else if (!strcmp("a", mode) || !strcmp("ab", mode) || !strcmp("a+", mode) || !strcmp("ab+", mode) || !strcmp("a+b", mode) ) {
  108. // 先看看是否存在, 如果存在就重用老的
  109. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  110. {
  111. if (files[i] == NULL)
  112. continue;
  113. if (!strcmp(files[i]->name, filename)) {
  114. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  115. if (fd == NULL) {
  116. LLOGE("out of memory when malloc luat_raw_fd_t");
  117. return NULL;
  118. }
  119. fd->fid = i;
  120. fd->offset = files[i]->size;
  121. fd->readonly = 0;
  122. return (FILE*)fd;
  123. }
  124. }
  125. LLOGW("file %s not found, can't open with mode %s", filename, mode);
  126. return NULL;
  127. }
  128. else {
  129. LLOGE("unkown open mode %s", mode);
  130. return NULL;
  131. }
  132. LLOGE("too many ram files >= %d", RAM_FILE_MAX);
  133. return NULL;
  134. }
  135. int luat_vfs_ram_getc(void* userdata, FILE* stream) {
  136. uint8_t c = 0;
  137. size_t len = luat_vfs_ram_fread(userdata, &c, 1, 1, stream);
  138. if (len == 1) {
  139. return c;
  140. }
  141. return -1;
  142. }
  143. int luat_vfs_ram_fseek(void* userdata, FILE* stream, long int offset, int origin) {
  144. (void)userdata;
  145. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  146. // LLOGE("luat_vfs_ram_fseek seek %p %p %d %d", userdata, stream, offset, origin);
  147. if (origin == SEEK_CUR) {
  148. fd->offset += offset;
  149. }
  150. else if (origin == SEEK_SET) {
  151. fd->offset = offset;
  152. }
  153. else {
  154. fd->offset = files[fd->fid]->size - offset;
  155. }
  156. if (fd->offset > files[fd->fid]->size) {
  157. // 如果偏移量超过了文件大小,设置为文件大小
  158. fd->offset = files[fd->fid]->size;
  159. }
  160. return 0;
  161. }
  162. int luat_vfs_ram_ftell(void* userdata, FILE* stream) {
  163. (void)userdata;
  164. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  165. // LLOGD("tell %p %p offset %d", userdata, stream, fd->offset);
  166. return fd->offset;
  167. }
  168. int luat_vfs_ram_fclose(void* userdata, FILE* stream) {
  169. (void)userdata;
  170. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  171. //LLOGD("fclose %p %p %d %d", userdata, stream, fd->size, fd->offset);
  172. luat_heap_free(fd);
  173. return 0;
  174. }
  175. int luat_vfs_ram_feof(void* userdata, FILE* stream) {
  176. (void)userdata;
  177. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  178. //LLOGD("feof %p %p %d %d", userdata, stream, fd->size, fd->offset);
  179. return fd->offset >= files[fd->fid]->size ? 1 : 0;
  180. }
  181. int luat_vfs_ram_ferror(void* userdata, FILE *stream) {
  182. (void)userdata;
  183. (void)stream;
  184. return 0;
  185. }
  186. size_t luat_vfs_ram_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream) {
  187. (void)userdata;
  188. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  189. size_t read_size = size * nmemb;
  190. // 如果偏移量已经超出文件大小
  191. if (fd->offset >= files[fd->fid]->size) {
  192. return 0;
  193. }
  194. // 如果读取的大小超出文件剩余大小,调整读取大小
  195. if (fd->offset + read_size > files[fd->fid]->size) {
  196. read_size = files[fd->fid]->size - fd->offset;
  197. }
  198. // 找到offset对应的起始block
  199. ram_file_block_t* block = files[fd->fid]->head;
  200. size_t offset = fd->offset;
  201. while (block != NULL && offset >= BLOCK_SIZE) {
  202. offset -= BLOCK_SIZE;
  203. block = block->next;
  204. }
  205. // 如果没有找到对应的block
  206. if (block == NULL) {
  207. LLOGW("no block for offset %d", fd->offset);
  208. return 0;
  209. }
  210. // 开始读取
  211. uint8_t* dst = (uint8_t*)ptr;
  212. size_t bytes_read = 0; // 用于记录实际读取的字节数
  213. while (block != NULL && read_size > 0) {
  214. size_t copy_size = BLOCK_SIZE - (offset % BLOCK_SIZE);
  215. if (copy_size > read_size) {
  216. copy_size = read_size;
  217. }
  218. memcpy(dst, block->data + (offset % BLOCK_SIZE), copy_size);
  219. dst += copy_size;
  220. read_size -= copy_size;
  221. offset += copy_size;
  222. bytes_read += copy_size; // 累加读取的字节数
  223. if (offset % BLOCK_SIZE == 0) {
  224. block = block->next;
  225. }
  226. }
  227. fd->offset += bytes_read; // 更新文件偏移量
  228. return bytes_read; // 返回实际读取的字节数
  229. }
  230. size_t luat_vfs_ram_fwrite(void* userdata, const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  231. (void)userdata;
  232. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  233. size_t write_size = size * nmemb;
  234. if (fd->readonly) {
  235. LLOGW("readonly fd %d!! path %s", fd->fid, files[fd->fid]->name);
  236. return 0;
  237. }
  238. // 计算最终需要的总大小
  239. size_t total_size = fd->offset + write_size;
  240. // size_t current_size = files[fd->fid]->size; // 当前文件大小
  241. // 先补齐block
  242. ram_file_block_t* block = files[fd->fid]->head;
  243. size_t block_offset = 0; // 当前block的偏移量
  244. // 遍历现有的block,直到block_offset达到total_size
  245. while (block != NULL && block_offset < total_size) {
  246. block_offset += BLOCK_SIZE;
  247. block = block->next;
  248. }
  249. // 如果block_offset小于total_size,继续分配新的block
  250. while (block_offset < total_size) {
  251. block = luat_heap_malloc(sizeof(ram_file_block_t));
  252. if (block == NULL) {
  253. LLOGW("out of memory when malloc ram_file_block_t");
  254. return 0;
  255. }
  256. memset(block, 0, sizeof(ram_file_block_t));
  257. block->next = NULL;
  258. // 将新分配的block链接到链表末尾
  259. if (files[fd->fid]->head == NULL) {
  260. files[fd->fid]->head = block;
  261. } else {
  262. ram_file_block_t* last = files[fd->fid]->head;
  263. while (last->next) {
  264. last = last->next;
  265. }
  266. last->next = block;
  267. }
  268. block_offset += BLOCK_SIZE;
  269. }
  270. // 现在偏移到offset对应的block
  271. block = files[fd->fid]->head;
  272. size_t offset = fd->offset;
  273. while (block != NULL && offset >= BLOCK_SIZE) {
  274. offset -= BLOCK_SIZE;
  275. block = block->next;
  276. }
  277. // 开始写
  278. const uint8_t* src = (const uint8_t*)ptr;
  279. while (write_size > 0) {
  280. size_t copy_size = BLOCK_SIZE - (offset % BLOCK_SIZE);
  281. if (copy_size > write_size) {
  282. copy_size = write_size;
  283. }
  284. memcpy(block->data + (offset % BLOCK_SIZE), src, copy_size);
  285. src += copy_size;
  286. write_size -= copy_size;
  287. offset += copy_size;
  288. if (offset % BLOCK_SIZE == 0) {
  289. block = block->next;
  290. }
  291. }
  292. fd->offset += (size_t)(src - (const uint8_t*)ptr);
  293. // 更新文件大小
  294. files[fd->fid]->size = total_size;
  295. // 打印一下写入的数据
  296. // LLOGD("write data %s", (char*)ptr);
  297. return (size_t)(src - (const uint8_t*)ptr);
  298. }
  299. int luat_vfs_ram_remove(void* userdata, const char *filename) {
  300. (void)userdata;
  301. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  302. {
  303. if (files[i] == NULL)
  304. continue;
  305. if (!strcmp(filename, files[i]->name)) {
  306. ram_file_block_t* block = files[i]->head;
  307. while (block) {
  308. ram_file_block_t* next = block->next;
  309. luat_heap_free(block);
  310. block = next;
  311. }
  312. luat_heap_free(files[i]);
  313. files[i] = NULL;
  314. return 0;
  315. }
  316. }
  317. return 0;
  318. }
  319. int luat_vfs_ram_rename(void* userdata, const char *old_filename, const char *new_filename) {
  320. (void)userdata;
  321. if (old_filename == NULL || new_filename == NULL)
  322. return -1;
  323. if (strlen(old_filename) > 31 || strlen(new_filename) > 31)
  324. return -2;
  325. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  326. {
  327. if (files[i] == NULL)
  328. continue;
  329. if (!strcmp(old_filename, files[i]->name)) {
  330. strcpy(files[i]->name, new_filename);
  331. return 0;
  332. }
  333. }
  334. return 0;
  335. }
  336. int luat_vfs_ram_fexist(void* userdata, const char *filename) {
  337. (void)userdata;
  338. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  339. {
  340. if (files[i] == NULL)
  341. continue;
  342. if (!strcmp(filename, files[i]->name)) {
  343. return 1;
  344. }
  345. }
  346. return 0;
  347. }
  348. size_t luat_vfs_ram_fsize(void* userdata, const char *filename) {
  349. (void)userdata;
  350. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  351. {
  352. if (files[i] == NULL)
  353. continue;
  354. if (!strcmp(filename, files[i]->name)) {
  355. return files[i]->size;
  356. }
  357. }
  358. return 0;
  359. }
  360. void* luat_vfs_ram_mmap(void* userdata, FILE *stream) {
  361. (void)userdata;
  362. luat_raw_fd_t *fd = (luat_raw_fd_t*)(stream);
  363. //LLOGD("fsize %p %p %d %d", userdata, fd);
  364. return files[fd->fid]->head->data;
  365. }
  366. int luat_vfs_ram_mkfs(void* userdata, luat_fs_conf_t *conf) {
  367. (void)userdata;
  368. (void)conf;
  369. return -1;
  370. }
  371. int luat_vfs_ram_mount(void** userdata, luat_fs_conf_t *conf) {
  372. (void)userdata;
  373. (void)conf;
  374. return 0;
  375. }
  376. int luat_vfs_ram_umount(void* userdata, luat_fs_conf_t *conf) {
  377. (void)userdata;
  378. (void)conf;
  379. return 0;
  380. }
  381. int luat_vfs_ram_mkdir(void* userdata, char const* _DirName) {
  382. (void)userdata;
  383. (void)_DirName;
  384. return -1;
  385. }
  386. int luat_vfs_ram_rmdir(void* userdata, char const* _DirName) {
  387. (void)userdata;
  388. (void)_DirName;
  389. return -1;
  390. }
  391. int luat_vfs_ram_lsdir(void* userdata, char const* _DirName, luat_fs_dirent_t* ents, size_t offset, size_t len) {
  392. (void)userdata;
  393. (void)_DirName;
  394. size_t count = 0;
  395. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  396. {
  397. if (count >= len)
  398. break;
  399. if (files[i] == NULL)
  400. continue;
  401. if (offset > 0) {
  402. offset --;
  403. continue;
  404. }
  405. ents[count].d_type = 0;
  406. strcpy(ents[count].d_name, files[i]->name);
  407. count ++;
  408. }
  409. return count;
  410. }
  411. int luat_vfs_ram_info(void* userdata, const char* path, luat_fs_info_t *conf) {
  412. (void)userdata;
  413. (void)path;
  414. memcpy(conf->filesystem, "ram", strlen("ram")+1);
  415. size_t ftotal = 0;
  416. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  417. {
  418. if (files[i] == NULL)
  419. continue;
  420. ftotal += files[i]->size;
  421. }
  422. size_t total; size_t used; size_t max_used;
  423. luat_meminfo_sys(&total, &used, &max_used);
  424. conf->type = 0;
  425. conf->total_block = 64;
  426. conf->block_used = (ftotal + BLOCK_SIZE) / BLOCK_SIZE;
  427. conf->block_size = BLOCK_SIZE;
  428. return 0;
  429. }
  430. int luat_vfs_ram_truncate(void* fsdata, char const* path, size_t nsize) {
  431. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  432. {
  433. if (files[i] == NULL)
  434. continue;
  435. if (!strcmp(files[i]->name, path)) {
  436. ram_file_block_t* block = files[i]->head;
  437. size_t offset = 0;
  438. while (block) {
  439. if (offset + BLOCK_SIZE > nsize) {
  440. memset(block->data + (nsize - offset), 0, BLOCK_SIZE - (nsize - offset));
  441. }
  442. offset += BLOCK_SIZE;
  443. block = block->next;
  444. }
  445. files[i]->size = nsize;
  446. return 0;
  447. }
  448. }
  449. return 0;
  450. }
  451. #else
  452. typedef struct ram_file
  453. {
  454. size_t size; // 当前文件大小, 也是指针对应内存块的大小
  455. // size_t ptr_size; // 数值指针的大小
  456. char name[32]; // 文件名称
  457. char ptr[4];
  458. }ram_file_t;
  459. typedef struct luat_ram_fd
  460. {
  461. int fid;
  462. uint32_t offset;
  463. uint8_t readonly;
  464. }luat_raw_fd_t;
  465. #define RAM_FILE_MAX (64)
  466. static ram_file_t* files[RAM_FILE_MAX];
  467. FILE* luat_vfs_ram_fopen(void* userdata, const char *filename, const char *mode) {
  468. (void)userdata;
  469. // LLOGD("ram fs open %s %s", filename, mode);
  470. if (filename == NULL || mode == NULL || strlen(filename) > 31)
  471. return NULL;
  472. // 读文件
  473. if (!strcmp("r", mode) || !strcmp("rb", mode)) {
  474. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  475. {
  476. if (files[i]== NULL)
  477. continue;
  478. if (!strcmp(files[i]->name, filename)) {
  479. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  480. if (fd == NULL) {
  481. LLOGE("out of memory when malloc luat_raw_fd_t");
  482. return NULL;
  483. }
  484. fd->fid = i;
  485. fd->offset = 0;
  486. fd->readonly = 1;
  487. return (FILE*)fd;
  488. }
  489. }
  490. return NULL;
  491. }
  492. // 写文件
  493. else if (!strcmp("w", mode) || !strcmp("wb", mode) || !strcmp("w+", mode) || !strcmp("wb+", mode) || !strcmp("w+b", mode) || !strcmp("r+", mode) || !strcmp("rb+", mode) || !strcmp("r+b", mode)) {
  494. // 先看看是否存在, 如果存在就重用老的
  495. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  496. {
  497. if (files[i]== NULL)
  498. continue;
  499. if (!strcmp(files[i]->name, filename)) {
  500. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  501. if (fd == NULL) {
  502. LLOGE("out of memory when malloc luat_raw_fd_t");
  503. return NULL;
  504. }
  505. fd->fid = i;
  506. fd->readonly = 0;
  507. fd->offset = 0;
  508. if (!strcmp("w+", mode) || !strcmp("wb+", mode) || !strcmp("w+b", mode)) {
  509. // 截断模式
  510. char* tmp = luat_heap_realloc(files[i], sizeof(ram_file_t));
  511. if (tmp) {
  512. files[i] = (ram_file_t*)tmp;
  513. }
  514. else {
  515. LLOGE("realloc ram_file_t failed");
  516. luat_heap_free(fd);
  517. return NULL;
  518. }
  519. files[i]->size = 0;
  520. }
  521. return (FILE*)fd;
  522. }
  523. }
  524. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  525. {
  526. if (files[i] != NULL)
  527. continue;
  528. ram_file_t *file = luat_heap_malloc(sizeof(ram_file_t));
  529. if (file == NULL) {
  530. LLOGE("out of memory when malloc ram_file_t");
  531. return NULL;
  532. }
  533. memset(file, 0, sizeof(ram_file_t));
  534. strcpy(file->name, filename);
  535. files[i] = file;
  536. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  537. if (fd == NULL) {
  538. LLOGE("out of memory when malloc luat_raw_fd_t");
  539. return NULL;
  540. }
  541. fd->fid = i;
  542. fd->offset = 0;
  543. fd->readonly = 0;
  544. return (FILE*)fd;
  545. }
  546. }
  547. // 追加模式
  548. else if (!strcmp("a", mode) || !strcmp("ab", mode) || !strcmp("a+", mode) || !strcmp("ab+", mode) || !strcmp("a+b", mode) ) {
  549. // 先看看是否存在, 如果存在就重用老的
  550. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  551. {
  552. if (files[i] == NULL)
  553. continue;
  554. if (!strcmp(files[i]->name, filename)) {
  555. luat_raw_fd_t* fd = luat_heap_malloc(sizeof(luat_raw_fd_t));
  556. if (fd == NULL) {
  557. LLOGE("out of memory when malloc luat_raw_fd_t");
  558. return NULL;
  559. }
  560. fd->fid = i;
  561. fd->offset = files[i]->size;
  562. fd->readonly = 0;
  563. return (FILE*)fd;
  564. }
  565. }
  566. }
  567. else {
  568. LLOGE("unkown open mode %s", mode);
  569. return NULL;
  570. }
  571. LLOGE("too many ram files >= %d", RAM_FILE_MAX);
  572. return NULL;
  573. }
  574. int luat_vfs_ram_getc(void* userdata, FILE* stream) {
  575. (void)userdata;
  576. //LLOGD("getc %p %p", userdata, stream);
  577. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  578. //LLOGD("getc %p %p %d %d", userdata, stream, fd->offset, fd->size);
  579. if (fd->fid < 0 || fd->fid >= RAM_FILE_MAX) {
  580. return -1;
  581. }
  582. if (files[fd->fid] == NULL) {
  583. return -1;
  584. }
  585. if (fd->offset < files[fd->fid]->size) {
  586. uint8_t c = (uint8_t)files[fd->fid]->ptr[fd->offset];
  587. fd->offset ++;
  588. //LLOGD("getc %02X", c);
  589. return c;
  590. }
  591. return -1;
  592. }
  593. int luat_vfs_ram_fseek(void* userdata, FILE* stream, long int offset, int origin) {
  594. (void)userdata;
  595. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  596. if (origin == SEEK_CUR) {
  597. fd->offset += offset;
  598. return 0;
  599. }
  600. else if (origin == SEEK_SET) {
  601. fd->offset = offset;
  602. return 0;
  603. }
  604. else {
  605. fd->offset = files[fd->fid]->size - offset;
  606. return 0;
  607. }
  608. }
  609. int luat_vfs_ram_ftell(void* userdata, FILE* stream) {
  610. (void)userdata;
  611. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  612. // LLOGD("tell %p %p offset %d", userdata, stream, fd->offset);
  613. return fd->offset;
  614. }
  615. int luat_vfs_ram_fclose(void* userdata, FILE* stream) {
  616. (void)userdata;
  617. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  618. //LLOGD("fclose %p %p %d %d", userdata, stream, fd->size, fd->offset);
  619. luat_heap_free(fd);
  620. return 0;
  621. }
  622. int luat_vfs_ram_feof(void* userdata, FILE* stream) {
  623. (void)userdata;
  624. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  625. //LLOGD("feof %p %p %d %d", userdata, stream, fd->size, fd->offset);
  626. return fd->offset >= files[fd->fid]->size ? 1 : 0;
  627. }
  628. int luat_vfs_ram_ferror(void* userdata, FILE *stream) {
  629. (void)userdata;
  630. (void)stream;
  631. return 0;
  632. }
  633. size_t luat_vfs_ram_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream) {
  634. (void)userdata;
  635. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  636. //LLOGD("fread %p %p %d %d", userdata, stream, fd->size, fd->offset);
  637. //LLOGD("fread2 %p %p %d %d", userdata, stream, size * nmemb, fd->offset);
  638. size_t read_size = size*nmemb;
  639. if (fd->offset >= files[fd->fid]->size) {
  640. return 0;
  641. }
  642. if (fd->offset + read_size >= files[fd->fid]->size) {
  643. read_size = files[fd->fid]->size - fd->offset;
  644. }
  645. memcpy(ptr, files[fd->fid]->ptr + fd->offset, read_size);
  646. fd->offset += read_size;
  647. return read_size;
  648. }
  649. size_t luat_vfs_ram_fwrite(void* userdata, const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  650. (void)userdata;
  651. luat_raw_fd_t* fd = (luat_raw_fd_t*)stream;
  652. size_t write_size = size*nmemb;
  653. if (write_size > 128 * 1024) {
  654. LLOGW("ramfs large write !! %ld", write_size);
  655. }
  656. if (fd->readonly) {
  657. LLOGW("readonly fd %d!! path %s", fd->fid, files[fd->fid]->name);
  658. return 0;
  659. }
  660. if (fd->offset + write_size > files[fd->fid]->size) {
  661. char* ptr = luat_heap_realloc(files[fd->fid], fd->offset + write_size + sizeof(ram_file_t));
  662. if (ptr == NULL) {
  663. LLOGW("/ram out of sys memory!! %ld", write_size);
  664. return 0;
  665. }
  666. files[fd->fid] = (ram_file_t*)ptr;
  667. files[fd->fid]->size = fd->offset + write_size;
  668. }
  669. memcpy(files[fd->fid]->ptr + fd->offset, ptr, write_size);
  670. fd->offset += write_size;
  671. return write_size;
  672. }
  673. int luat_vfs_ram_remove(void* userdata, const char *filename) {
  674. (void)userdata;
  675. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  676. {
  677. if (files[i] == NULL)
  678. continue;
  679. if (!strcmp(filename, files[i]->name)) {
  680. luat_heap_free(files[i]);
  681. files[i] = NULL;
  682. }
  683. }
  684. return 0;
  685. }
  686. int luat_vfs_ram_rename(void* userdata, const char *old_filename, const char *new_filename) {
  687. (void)userdata;
  688. if (old_filename == NULL || new_filename == NULL)
  689. return -1;
  690. if (strlen(old_filename) > 31 || strlen(new_filename) > 31)
  691. return -2;
  692. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  693. {
  694. if (files[i] == NULL)
  695. continue;
  696. if (!strcmp(old_filename, files[i]->name)) {
  697. strcpy(files[i]->name, new_filename);
  698. return 0;
  699. }
  700. }
  701. return 0;
  702. }
  703. int luat_vfs_ram_fexist(void* userdata, const char *filename) {
  704. (void)userdata;
  705. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  706. {
  707. if (files[i] == NULL)
  708. continue;
  709. if (!strcmp(filename, files[i]->name)) {
  710. return 1;
  711. }
  712. }
  713. return 0;
  714. }
  715. size_t luat_vfs_ram_fsize(void* userdata, const char *filename) {
  716. (void)userdata;
  717. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  718. {
  719. if (files[i] == NULL)
  720. continue;
  721. if (!strcmp(filename, files[i]->name)) {
  722. return files[i]->size;
  723. }
  724. }
  725. return 0;
  726. }
  727. void* luat_vfs_ram_mmap(void* userdata, FILE *stream) {
  728. (void)userdata;
  729. luat_raw_fd_t *fd = (luat_raw_fd_t*)(stream);
  730. //LLOGD("fsize %p %p %d %d", userdata, fd);
  731. return files[fd->fid]->ptr;
  732. }
  733. int luat_vfs_ram_mkfs(void* userdata, luat_fs_conf_t *conf) {
  734. (void)userdata;
  735. (void)conf;
  736. return -1;
  737. }
  738. int luat_vfs_ram_mount(void** userdata, luat_fs_conf_t *conf) {
  739. (void)userdata;
  740. (void)conf;
  741. return 0;
  742. }
  743. int luat_vfs_ram_umount(void* userdata, luat_fs_conf_t *conf) {
  744. (void)userdata;
  745. (void)conf;
  746. return 0;
  747. }
  748. int luat_vfs_ram_mkdir(void* userdata, char const* _DirName) {
  749. (void)userdata;
  750. (void)_DirName;
  751. return -1;
  752. }
  753. int luat_vfs_ram_rmdir(void* userdata, char const* _DirName) {
  754. (void)userdata;
  755. (void)_DirName;
  756. return -1;
  757. }
  758. int luat_vfs_ram_lsdir(void* userdata, char const* _DirName, luat_fs_dirent_t* ents, size_t offset, size_t len) {
  759. (void)userdata;
  760. (void)_DirName;
  761. size_t count = 0;
  762. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  763. {
  764. if (count >= len)
  765. break;
  766. if (files[i] == NULL)
  767. continue;
  768. if (offset > 0) {
  769. offset --;
  770. continue;
  771. }
  772. ents[count].d_type = 0;
  773. strcpy(ents[count].d_name, files[i]->name);
  774. count ++;
  775. }
  776. return count;
  777. }
  778. int luat_vfs_ram_info(void* userdata, const char* path, luat_fs_info_t *conf) {
  779. (void)userdata;
  780. (void)path;
  781. memcpy(conf->filesystem, "ram", strlen("ram")+1);
  782. size_t ftotal = 0;
  783. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  784. {
  785. if (files[i] == NULL)
  786. continue;
  787. ftotal += files[i]->size;
  788. }
  789. size_t total; size_t used; size_t max_used;
  790. luat_meminfo_sys(&total, &used, &max_used);
  791. conf->type = 0;
  792. conf->total_block = 64;
  793. conf->block_used = (ftotal + 1023) / 1024;
  794. conf->block_size = 1024;
  795. return 0;
  796. }
  797. int luat_vfs_ram_truncate(void* fsdata, char const* path, size_t nsize) {
  798. for (size_t i = 0; i < RAM_FILE_MAX; i++)
  799. {
  800. if (files[i] == NULL)
  801. continue;
  802. if (!strcmp(files[i]->name, path)) {
  803. if (files[i]->size > nsize) {
  804. files[i]->size = nsize;
  805. char* ptr = luat_heap_realloc(files[i], nsize + sizeof(ram_file_t));
  806. if (ptr) {
  807. files[i] = (ram_file_t*)ptr;
  808. }
  809. }
  810. return 0;
  811. }
  812. }
  813. return 0;
  814. }
  815. #endif
  816. #define T(name) .name = luat_vfs_ram_##name
  817. const struct luat_vfs_filesystem vfs_fs_ram = {
  818. .name = "ram",
  819. .opts = {
  820. .mkfs = NULL,
  821. T(mount),
  822. T(umount),
  823. .mkdir = NULL,
  824. .rmdir = NULL,
  825. T(lsdir),
  826. T(remove),
  827. T(rename),
  828. T(fsize),
  829. T(fexist),
  830. T(info),
  831. T(truncate)
  832. },
  833. .fopts = {
  834. T(fopen),
  835. T(getc),
  836. T(fseek),
  837. T(ftell),
  838. T(fclose),
  839. T(feof),
  840. T(ferror),
  841. T(fread),
  842. T(fwrite)
  843. }
  844. };