luat_fs_luadb.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. #include "luat_base.h"
  2. #include "luat_luadb.h"
  3. #include "luat_mem.h"
  4. #include "luat_fs.h"
  5. #define LUAT_LOG_TAG "luadb"
  6. #include "luat_log.h"
  7. #undef LLOGD
  8. #define LLOGD(...)
  9. #ifndef LUAT_CONF_LUADB_CUSTOM_READ
  10. void luat_luadb_read_bytes(char* dst, const char* ptr, size_t len) {
  11. memcpy(dst, ptr, len);
  12. }
  13. static uint8_t readU8(const char* ptr, int *index) {
  14. int val = ptr[*index];
  15. *index = (*index) + 1;
  16. return val & 0xFF;
  17. }
  18. #else
  19. extern void luat_luadb_read_bytes(char* dst, const char* ptr, size_t len);
  20. static uint8_t readU8(const char* ptr, int *index) {
  21. char val = 0;
  22. luat_luadb_read_bytes(&val, ptr + (*index), 1);
  23. *index = (*index) + 1;
  24. return val & 0xFF;
  25. }
  26. #endif
  27. static uint16_t readU16(const char* ptr, int *index) {
  28. return readU8(ptr,index) + (readU8(ptr,index) << 8);
  29. }
  30. static uint32_t readU32(const char* ptr, int *index) {
  31. return readU16(ptr,index) + (readU16(ptr,index) << 16);
  32. }
  33. //---
  34. int luat_luadb_umount(luadb_fs_t *fs) {
  35. if (fs)
  36. luat_heap_free(fs);
  37. return 0;
  38. }
  39. int luat_luadb_remount(luadb_fs_t *fs, unsigned flags) {
  40. (void)flags;
  41. memset(fs->fds, 0, sizeof(luadb_fd_t)*LUAT_LUADB_MAX_OPENFILE);
  42. return 0;
  43. }
  44. static luadb_file_t* find_by_name(luadb_fs_t *fs, const char *path) {
  45. for (size_t i = 0; i < fs->filecount; i++)
  46. {
  47. if (!strcmp(path, fs->files[i].name)) {
  48. return &(fs->files[i]);
  49. }
  50. }
  51. // luadb_file_t *ext = fs->inlines;
  52. // while (ext->ptr != NULL)
  53. // {
  54. // if (!strcmp(path, ext->name)) {
  55. // return ext;
  56. // }
  57. // ext += 1;
  58. // }
  59. return NULL;
  60. }
  61. int luat_luadb_open(luadb_fs_t *fs, const char *path, int flags, int /*mode_t*/ mode) {
  62. (void)flags;
  63. (void)mode;
  64. LLOGD("open luadb path = %s flags=%d", path, flags);
  65. int fd = -1;
  66. for (size_t j = 1; j < LUAT_LUADB_MAX_OPENFILE; j++)
  67. {
  68. if (fs->fds[j].file == NULL) {
  69. fd = j;
  70. break;
  71. }
  72. }
  73. if (fd == -1) {
  74. LLOGD("too many open files for luadb");
  75. return 0;
  76. }
  77. luadb_file_t* f = find_by_name(fs, path);
  78. if (f != NULL) {
  79. fs->fds[fd].fd_pos = 0;
  80. fs->fds[fd].file = f;
  81. LLOGD("open luadb path = %s fd=%d", path, fd);
  82. return fd;
  83. }
  84. return 0;
  85. }
  86. int luat_luadb_close(luadb_fs_t *fs, int fd) {
  87. if (fd < 0 || fd >= LUAT_LUADB_MAX_OPENFILE)
  88. return -1;
  89. if (fs->fds[fd].file != NULL) {
  90. fs->fds[fd].file = NULL;
  91. fs->fds[fd].fd_pos = 0;
  92. return 0;
  93. }
  94. return -1;
  95. }
  96. size_t luat_luadb_read(luadb_fs_t *fs, int fd, void *dst, size_t size) {
  97. if (fd < 0 || fd >= LUAT_LUADB_MAX_OPENFILE || fs->fds[fd].file == NULL)
  98. return 0;
  99. luadb_fd_t *fdt = &fs->fds[fd];
  100. int re = size;
  101. if (fdt->fd_pos >= fdt->file->size) {
  102. //LLOGD("luadb read name %s offset %d size %d ret 0", fdt->file->name, fdt->fd_pos, size);
  103. return 0; // 已经读完了
  104. }
  105. if (fdt->fd_pos + size > fdt->file->size) {
  106. re = fdt->file->size - fdt->fd_pos;
  107. }
  108. if (re > 0) {
  109. #ifndef LUAT_CONF_LUADB_CUSTOM_READ
  110. memcpy(dst, fdt->file->ptr + fdt->fd_pos, re);
  111. #else
  112. luat_luadb_read_bytes(dst, fdt->file->ptr + fdt->fd_pos, re);
  113. #endif
  114. fdt->fd_pos += re;
  115. }
  116. //LLOGD("luadb read name %s offset %d size %d ret %d", fdt->file->name, fdt->fd_pos, size, re);
  117. return re > 0 ? re : 0;
  118. }
  119. long luat_luadb_lseek(luadb_fs_t *fs, int fd, long /*off_t*/ offset, int mode) {
  120. if (fd < 0 || fd >= LUAT_LUADB_MAX_OPENFILE || fs->fds[fd].file == NULL)
  121. return -1;
  122. if (mode == SEEK_END) {
  123. fs->fds[fd].fd_pos = fs->fds[fd].file->size - offset;
  124. }
  125. else if (mode == SEEK_CUR) {
  126. fs->fds[fd].fd_pos += offset;
  127. }
  128. else {
  129. fs->fds[fd].fd_pos = offset;
  130. }
  131. if (fs->fds[fd].fd_pos > fs->fds[fd].file->size) {
  132. fs->fds[fd].fd_pos = fs->fds[fd].file->size;
  133. }
  134. return fs->fds[fd].fd_pos;
  135. }
  136. luadb_file_t * luat_luadb_stat(luadb_fs_t *fs, const char *path) {
  137. return find_by_name(fs, path);
  138. }
  139. luadb_fs_t* luat_luadb_mount(const char* _ptr) {
  140. int index = 0;
  141. int headok = 0;
  142. int dbver = 0;
  143. int headsize = 0;
  144. size_t filecount = 0;
  145. const char * ptr = (const char *)_ptr;
  146. //LLOGD("LuaDB ptr = %p", ptr);
  147. uint16_t magic1 = 0;
  148. uint16_t magic2 = 0;
  149. for (size_t i = 0; i < 128; i++)
  150. {
  151. int type = readU8(ptr, &index);
  152. int len = readU8(ptr, &index);
  153. //LLOGD("PTR: %d %d %d", type, len, index);
  154. switch (type) {
  155. case 1: {// Magic, 肯定是4个字节
  156. if (len != 4) {
  157. LLOGD("Magic len != 4");
  158. goto _after_head;
  159. }
  160. magic1 = readU16(ptr, &index);
  161. magic2 = readU16(ptr, &index);
  162. if (magic1 != magic2 || magic1 != 0xA55A) {
  163. LLOGD("Magic not match 0x%04X%04X", magic1, magic2);
  164. goto _after_head;
  165. }
  166. break;
  167. }
  168. case 2: {
  169. if (len != 2) {
  170. LLOGD("Version len != 2");
  171. goto _after_head;
  172. }
  173. dbver = readU16(ptr, &index);
  174. LLOGD("LuaDB version = %d", dbver);
  175. break;
  176. }
  177. case 3: {
  178. if (len != 4) {
  179. LLOGD("Header full len != 4");
  180. goto _after_head;
  181. }
  182. headsize = readU32(ptr, &index);
  183. break;
  184. }
  185. case 4 : {
  186. if (len != 2) {
  187. LLOGD("Lua File Count len != 4");
  188. goto _after_head;
  189. }
  190. filecount = readU16(ptr, &index);
  191. LLOGD("LuaDB file count %d", filecount);
  192. break;
  193. }
  194. case 0xFE : {
  195. if (len != 2) {
  196. LLOGD("CRC len != 4");
  197. goto _after_head;
  198. }
  199. index += len;
  200. headok = 1;
  201. goto _after_head;
  202. }
  203. default: {
  204. index += len;
  205. LLOGD("skip unkown type %d", type);
  206. break;
  207. }
  208. }
  209. }
  210. _after_head:
  211. if (headok == 0) {
  212. LLOGW("Bad LuaDB");
  213. return NULL;
  214. }
  215. if (dbver == 0) {
  216. LLOGW("miss DB version");
  217. return NULL;
  218. }
  219. if (headsize == 0) {
  220. LLOGW("miss DB headsize");
  221. return NULL;
  222. }
  223. if (filecount == 0) {
  224. LLOGW("miss DB filecount");
  225. return NULL;
  226. }
  227. if (filecount > 1024) {
  228. LLOGW("too many file in LuaDB");
  229. return NULL;
  230. }
  231. LLOGD("LuaDB head seem ok");
  232. // 由于luadb_fs_t带了一个luadb_file_t元素的
  233. size_t msize = sizeof(luadb_fs_t) + (filecount - 1)*sizeof(luadb_file_t);
  234. LLOGD("malloc fo luadb fs size=%d", msize);
  235. luadb_fs_t *fs = (luadb_fs_t*)luat_heap_malloc(msize);
  236. if (fs == NULL) {
  237. LLOGD("malloc for luadb fail!!!");
  238. return NULL;
  239. }
  240. memset(fs, 0, msize);
  241. LLOGD("LuaDB check files ....");
  242. fs->version = dbver;
  243. fs->filecount = filecount;
  244. //fs->ptrpos = initpos;
  245. int fail = 0;
  246. uint8_t type = 0;
  247. uint32_t len = 0;
  248. // int hasSys = 0;
  249. // 读取每个文件的头部
  250. for (size_t i = 0; i < filecount; i++)
  251. {
  252. LLOGD("LuaDB check files .... %d", i+1);
  253. type = readU8(ptr, &index);
  254. len = readU8(ptr, &index);
  255. if (type != 1 || len != 4) {
  256. LLOGD("bad file data 1 : %d %d %d", type, len, index);
  257. fail = 1;
  258. break;
  259. }
  260. // skip magic
  261. index += 4;
  262. // 2. 然后是名字
  263. type = readU8(ptr, &index);
  264. len = readU8(ptr, &index);
  265. if (type != 2) {
  266. LLOGD("bad file data 2 : %d %d %d", type, len, index);
  267. fail = 1;
  268. break;
  269. }
  270. // 拷贝文件名
  271. LLOGD("LuaDB file name len = %d", len);
  272. #ifndef LUAT_CONF_LUADB_CUSTOM_READ
  273. memcpy(fs->files[i].name, &(ptr[index]), len);
  274. #else
  275. luat_luadb_read_bytes(fs->files[i].name, ptr + index, len);
  276. #endif
  277. fs->files[i].name[len] = 0x00;
  278. index += len;
  279. LLOGD("LuaDB file name %.*s", len, fs->files[i].name);
  280. // 3. 文件大小
  281. type = readU8(ptr, &index);
  282. len = readU8(ptr, &index);
  283. if (type != 3 || len != 4) {
  284. LLOGD("bad file data 3 : %d %d %d", type, len, index);
  285. fail = 1;
  286. break;
  287. }
  288. fs->files[i].size = readU32(ptr, &index);
  289. // 0xFE校验码
  290. type = readU8(ptr, &index);
  291. len = readU8(ptr, &index);
  292. if (type != 0xFE || len != 2) {
  293. LLOGD("bad file data 4 : %d %d %d", type, len, index);
  294. fail = 1;
  295. break;
  296. }
  297. // 校验码就跳过吧
  298. index += len;
  299. fs->files[i].ptr = (const char*)(index + ptr); // 绝对地址
  300. index += fs->files[i].size;
  301. LLOGD("LuaDB: %s %d", fs->files[i].name, fs->files[i].size);
  302. }
  303. if (fail == 0) {
  304. LLOGD("LuaDB check files .... ok");
  305. // #ifdef LUAT_CONF_VM_64bit
  306. // //#if (sizeof(size_t) == 8)
  307. // //fs->inlines = (luadb_file_t *)luat_inline2_libs_64bit_size64;
  308. // //#else
  309. // fs->inlines = (luadb_file_t *)luat_inline2_libs_64bit_size32;
  310. // //#endif
  311. // #else
  312. // fs->inlines = (luadb_file_t *)luat_inline2_libs;
  313. // #endif
  314. return fs;
  315. }
  316. else {
  317. LLOGD("LuaDB check files .... fail");
  318. luat_heap_free(fs);
  319. return NULL;
  320. }
  321. }
  322. #ifdef LUAT_USE_FS_VFS
  323. FILE* luat_vfs_luadb_fopen(void* userdata, const char *filename, const char *mode) {
  324. if (!strcmp("r", mode) || !strcmp("rb", mode) || !strcmp("r+", mode) || !strcmp("rb+", mode)) {
  325. }
  326. else {
  327. LLOGW("/luadb is readonly %s %s", filename, mode);
  328. return (FILE*)NULL;
  329. }
  330. return (FILE*)luat_luadb_open((luadb_fs_t*)userdata, filename, 0, 0);
  331. }
  332. int luat_vfs_luadb_fseek(void* userdata, FILE* stream, long int offset, int origin) {
  333. int ret = luat_luadb_lseek((luadb_fs_t*)userdata, (int)stream, offset, origin);
  334. if (ret < 0)
  335. return -1;
  336. return 0;
  337. }
  338. int luat_vfs_luadb_ftell(void* userdata, FILE* stream) {
  339. return luat_luadb_lseek((luadb_fs_t*)userdata, (int)stream, 0, SEEK_CUR);
  340. }
  341. int luat_vfs_luadb_fclose(void* userdata, FILE* stream) {
  342. return luat_luadb_close((luadb_fs_t*)userdata, (int)stream);
  343. }
  344. int luat_vfs_luadb_feof(void* userdata, FILE* stream) {
  345. int cur = luat_luadb_lseek((luadb_fs_t*)userdata, (int)stream, 0, SEEK_CUR);
  346. int end = luat_luadb_lseek((luadb_fs_t*)userdata, (int)stream, 0, SEEK_END);
  347. luat_luadb_lseek((luadb_fs_t*)userdata, (int)stream, cur, SEEK_SET);
  348. return cur >= end ? 1 : 0;
  349. }
  350. int luat_vfs_luadb_ferror(void* userdata, FILE *stream) {
  351. (void)userdata;
  352. (void)stream;
  353. return 0;
  354. }
  355. size_t luat_vfs_luadb_fread(void* userdata, void *ptr, size_t size, size_t nmemb, FILE *stream) {
  356. return luat_luadb_read((luadb_fs_t*)userdata, (int)stream, ptr, size * nmemb);
  357. }
  358. int luat_vfs_luadb_getc(void* userdata, FILE* stream) {
  359. char c = 0;
  360. size_t ret = luat_vfs_luadb_fread((luadb_fs_t*)userdata, &c, 1, 1, stream);
  361. if (ret > 0) {
  362. return (int)c;
  363. }
  364. return -1;
  365. }
  366. size_t luat_vfs_luadb_fwrite(void* userdata, const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  367. (void)userdata;
  368. (void)stream;
  369. (void)ptr;
  370. (void)size;
  371. (void)nmemb;
  372. return 0;
  373. }
  374. int luat_vfs_luadb_remove(void* userdata, const char *filename) {
  375. (void)userdata;
  376. (void)filename;
  377. LLOGW("/luadb is readonly %s", filename);
  378. return -1;
  379. }
  380. int luat_vfs_luadb_rename(void* userdata, const char *old_filename, const char *new_filename) {
  381. (void)userdata;
  382. (void)old_filename;
  383. (void)new_filename;
  384. LLOGW("/luadb is readonly %s", old_filename);
  385. return -1;
  386. }
  387. int luat_vfs_luadb_fexist(void* userdata, const char *filename) {
  388. FILE* fd = luat_vfs_luadb_fopen(userdata, filename, "rb");
  389. if (fd) {
  390. luat_vfs_luadb_fclose(userdata, fd);
  391. return 1;
  392. }
  393. return 0;
  394. }
  395. size_t luat_vfs_luadb_fsize(void* userdata, const char *filename) {
  396. FILE *fd;
  397. size_t size = 0;
  398. fd = luat_vfs_luadb_fopen(userdata, filename, "rb");
  399. if (fd) {
  400. luat_vfs_luadb_fseek(userdata, fd, 0, SEEK_END);
  401. size = luat_vfs_luadb_ftell(userdata, fd);
  402. luat_vfs_luadb_fclose(userdata, fd);
  403. }
  404. return size;
  405. }
  406. int luat_vfs_luadb_mkfs(void* userdata, luat_fs_conf_t *conf) {
  407. //LLOGE("not support yet : mkfs");
  408. (void)userdata;
  409. (void)conf;
  410. return -1;
  411. }
  412. int luat_vfs_luadb_mount(void** userdata, luat_fs_conf_t *conf) {
  413. luadb_fs_t* fs = luat_luadb_mount((const char*)conf->busname);
  414. if (fs == NULL)
  415. return -1;
  416. *userdata = fs;
  417. return 0;
  418. }
  419. int luat_vfs_luadb_umount(void* userdata, luat_fs_conf_t *conf) {
  420. //LLOGE("not support yet : umount");
  421. (void)userdata;
  422. (void)conf;
  423. return 0;
  424. }
  425. int luat_vfs_luadb_mkdir(void* userdata, char const* _DirName) {
  426. //LLOGE("not support yet : mkdir");
  427. (void)userdata;
  428. (void)_DirName;
  429. return -1;
  430. }
  431. int luat_vfs_luadb_rmdir(void* userdata, char const* _DirName) {
  432. //LLOGE("not support yet : rmdir");
  433. (void)userdata;
  434. (void)_DirName;
  435. return -1;
  436. }
  437. int luat_vfs_luadb_lsdir(void* userdata, char const* _DirName, luat_fs_dirent_t* ents, size_t offset, size_t len) {
  438. (void)_DirName;
  439. luadb_fs_t* fs = (luadb_fs_t*)userdata;
  440. if (fs->filecount > offset) {
  441. if (offset + len > fs->filecount)
  442. len = fs->filecount - offset;
  443. for (size_t i = 0; i < len; i++)
  444. {
  445. ents[i].d_type = 0;
  446. strcpy(ents[i].d_name, fs->files[i+offset].name);
  447. }
  448. return len;
  449. }
  450. return 0;
  451. }
  452. // 这个全局变量是给bsp自行设置的,名字不要动
  453. size_t luat_luadb_act_size;
  454. int luat_vfs_luadb_info(void* userdata, const char* path, luat_fs_info_t *conf) {
  455. (void)path;
  456. memcpy(conf->filesystem, "luadb", strlen("luadb")+1);
  457. // 把luadb的第一个文件的偏移量估算为起始位置
  458. // 最后一个文件的偏移量+文件大小, 作为结束位置
  459. // 从而估算出luadb的实际用量
  460. size_t used = 0;
  461. luadb_fs_t* fs = (luadb_fs_t*)userdata;
  462. if (fs != NULL && fs->filecount > 0) {
  463. size_t begin = (size_t)fs->files[0].ptr;
  464. size_t end = (size_t)(fs->files[fs->filecount - 1].ptr) + fs->files[fs->filecount - 1].size;
  465. used = end - begin + 512;
  466. }
  467. conf->type = 0;
  468. conf->total_block = luat_luadb_act_size / 512;
  469. conf->block_used = (used / 512) + 1;
  470. conf->block_size = 512;
  471. return 0;
  472. }
  473. void* luat_vfs_luadb_mmap(void* userdata, FILE* f) {
  474. luadb_fs_t* fs = (luadb_fs_t*)userdata;
  475. int fd = (int)f;
  476. if (fd < 0 || fd >= LUAT_LUADB_MAX_OPENFILE || fs->fds[(int)fd].file == NULL)
  477. return 0;
  478. luadb_fd_t *fdt = &fs->fds[(int)fd];
  479. if (fdt != NULL) {
  480. return (void*)fdt->file->ptr;
  481. }
  482. return NULL;
  483. }
  484. #define T(name) .name = luat_vfs_luadb_##name
  485. const struct luat_vfs_filesystem vfs_fs_luadb = {
  486. .name = "luadb",
  487. .opts = {
  488. .mkfs = NULL,
  489. T(mount),
  490. T(umount),
  491. .mkdir = NULL,
  492. .rmdir = NULL,
  493. T(lsdir),
  494. .remove = NULL,
  495. .rename = NULL,
  496. T(fsize),
  497. T(fexist),
  498. T(info)
  499. },
  500. .fopts = {
  501. T(fopen),
  502. T(getc),
  503. T(fseek),
  504. T(ftell),
  505. T(fclose),
  506. T(feof),
  507. T(ferror),
  508. T(fread),
  509. #ifndef LUAT_CONF_LUADB_CUSTOM_READ
  510. T(mmap),
  511. #endif
  512. .fwrite = NULL
  513. }
  514. };
  515. #endif