luat_cmds.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. #include "luat_base.h"
  2. #include "luat_fs.h"
  3. #include "luat_malloc.h"
  4. #include "lundump.h"
  5. #include "luat_mock.h"
  6. #include "luat_luadb2.h"
  7. #include <stdlib.h>
  8. #define LUAT_LOG_TAG "fs"
  9. #include "luat_log.h"
  10. #include "dirent.h"
  11. extern int cmdline_argc;
  12. extern char **cmdline_argv;
  13. // luadb数据的上下文
  14. luat_luadb2_ctx_t luadb_ctx = {0};
  15. char *luadb_ptr;
  16. // 导出luadb数据的路径,默认是导出
  17. char luadb_dump_path[1024];
  18. // 脚本lua文件转luac时,是否删除调试信息,默认不删
  19. int cfg_luac_strip;
  20. int cfg_dump_luadb;
  21. int cfg_dump_report;
  22. int cfg_norun;
  23. void *check_file_path(const char *path);
  24. static int luat_cmd_load_luadb(const char *path);
  25. static int luat_cmd_load_luatools(const char *path);
  26. int luadb_do_report(luat_luadb2_ctx_t *ctx);
  27. static int is_opts(const char *key, const char *arg)
  28. {
  29. if (strlen(key) >= strlen(arg))
  30. {
  31. return 0;
  32. }
  33. return memcmp(key, arg, strlen(key)) == 0;
  34. }
  35. int luat_cmd_parse(int argc, char **argv)
  36. {
  37. if (cmdline_argc == 1)
  38. {
  39. return 0;
  40. }
  41. luat_luadb2_init(&luadb_ctx);
  42. for (size_t i = 1; i < (size_t)argc; i++)
  43. {
  44. const char *arg = argv[i];
  45. // 加载luadb文件镜像直接启动
  46. if (is_opts("--load_luadb=", arg))
  47. {
  48. if (luat_cmd_load_luadb(arg + strlen("--load_luadb=")))
  49. {
  50. LLOGE("加载luadb镜像失败");
  51. return -1;
  52. }
  53. continue;
  54. }
  55. if (is_opts("--ldb=", arg))
  56. {
  57. if (luat_cmd_load_luadb(arg + strlen("--ldb=")))
  58. {
  59. LLOGE("加载luadb镜像失败");
  60. return -1;
  61. }
  62. continue;
  63. }
  64. // 加载LuaTools项目文件直接启动
  65. if (is_opts("--load_luatools=", arg))
  66. {
  67. if (luat_cmd_load_luatools(arg + strlen("--load_luatools=")))
  68. {
  69. LLOGE("加载luatools项目文件失败");
  70. return -1;
  71. }
  72. continue;
  73. }
  74. if (is_opts("--llt=", arg))
  75. {
  76. if (luat_cmd_load_luatools(arg + strlen("--llt=")))
  77. {
  78. LLOGE("加载luatools项目文件失败");
  79. return -1;
  80. }
  81. continue;
  82. }
  83. // mock加载
  84. if (is_opts("--mlua=", arg))
  85. {
  86. if (luat_mock_init(arg + strlen("--mlua=")))
  87. {
  88. LLOGE("加载mock功能失败");
  89. return -1;
  90. }
  91. continue;
  92. }
  93. // 导出luadb文件
  94. if (is_opts("--dump_luadb=", arg))
  95. {
  96. memcpy(luadb_dump_path, arg + strlen("--dump_luadb="), strlen(arg) - strlen("--dump_luadb="));
  97. continue;
  98. }
  99. if (is_opts("--luac_strip=", arg))
  100. {
  101. if (!strcmp("--luac_strip=1", arg)) {
  102. cfg_luac_strip = 1;
  103. }
  104. else if (!strcmp("--luac_strip=0", arg)) {
  105. cfg_luac_strip = 0;
  106. }
  107. else if (!strcmp("--luac_strip=2", arg)) {
  108. cfg_luac_strip = 2;
  109. }
  110. continue;
  111. }
  112. if (is_opts("--luac_report=", arg))
  113. {
  114. // LLOGD("只导出luadb数据");
  115. if (!strcmp("--luac_report=1", arg)) {
  116. cfg_dump_report = 1;
  117. }
  118. continue;
  119. }
  120. // 是否导出luadb文件
  121. if (is_opts("--norun=", arg))
  122. {
  123. // LLOGD("只导出luadb数据");
  124. if (!strcmp("--norun=1", arg)) {
  125. cfg_norun = 1;
  126. }
  127. continue;
  128. }
  129. if (arg[0] == '-')
  130. {
  131. continue;
  132. }
  133. check_file_path(arg);
  134. }
  135. if (luadb_dump_path[0]) {
  136. LLOGD("导出luadb数据到 %s 大小 %d", luadb_dump_path, luadb_ctx.offset);
  137. FILE* f = fopen(luadb_dump_path, "wb+");
  138. if (f == NULL) {
  139. LLOGE("无法打开luadb导出路径 %s", luadb_dump_path);
  140. exit(1);
  141. }
  142. fwrite(luadb_ptr, 1, luadb_ctx.offset, f);
  143. fclose(f);
  144. }
  145. if (cfg_norun) {
  146. exit(0);
  147. }
  148. return 0;
  149. }
  150. static int luat_cmd_load_luadb(const char *path)
  151. {
  152. long len = 0;
  153. FILE *f = fopen(path, "rb");
  154. if (!f)
  155. {
  156. LLOGE("无法打开luadb镜像文件 %s", path);
  157. return -1;
  158. }
  159. fseek(f, 0, SEEK_END);
  160. len = ftell(f);
  161. fseek(f, 0, SEEK_SET);
  162. char *ptr = luat_heap_malloc(len);
  163. if (ptr == NULL)
  164. {
  165. fclose(f);
  166. LLOGE("luadb镜像文件太大,内存放不下 %s", path);
  167. return -1;
  168. }
  169. fread(ptr, len, 1, f);
  170. fclose(f);
  171. luadb_ptr = ptr;
  172. // luadb_offset = len;
  173. return 0;
  174. }
  175. static int luat_cmd_load_luatools(const char *path)
  176. {
  177. long len = 0;
  178. FILE *f = fopen(path, "rb");
  179. if (!f)
  180. {
  181. LLOGE("无法打开luatools项目文件 %s", path);
  182. return -1;
  183. }
  184. fseek(f, 0, SEEK_END);
  185. len = ftell(f);
  186. fseek(f, 0, SEEK_SET);
  187. char *ptr = luat_heap_malloc(len + 1);
  188. if (ptr == NULL)
  189. {
  190. fclose(f);
  191. LLOGE("luatools项目文件太大,内存放不下 %s", path);
  192. return -1;
  193. }
  194. fread(ptr, len, 1, f);
  195. fclose(f);
  196. ptr[len] = 0;
  197. char *ret = ptr;
  198. char dirline[512] = {0};
  199. char rpath[1024] = {0};
  200. size_t retlen = 0;
  201. while (ptr[0] != 0x00)
  202. {
  203. // LLOGD("ptr %c", ptr[0]);
  204. if (ptr[0] == '\r' || ptr[0] == '\n')
  205. {
  206. if (ret != ptr)
  207. {
  208. ptr[0] = 0x00;
  209. retlen = strlen(ret);
  210. // LLOGD("检索到的行 %s", ret);
  211. if (!strcmp("[info]", ret))
  212. {
  213. }
  214. else if (retlen > 5)
  215. {
  216. if (ret[0] == '[' && ret[retlen - 1] == ']')
  217. {
  218. LLOGD("目录行 %s", ret);
  219. memcpy(dirline, ret + 1, retlen - 2);
  220. dirline[retlen - 2] = 0x00;
  221. }
  222. else
  223. {
  224. if (dirline[0])
  225. {
  226. for (size_t i = 0; i < strlen(ret); i++)
  227. {
  228. if (ret[i] == ' ' || ret[i] == '=')
  229. {
  230. ret[i] = 0;
  231. memset(rpath, 0, 1024);
  232. memcpy(rpath, dirline, strlen(dirline));
  233. #ifdef LUA_USE_WINDOWS
  234. rpath[strlen(dirline)] = '\\';
  235. #else
  236. rpath[strlen(dirline)] = '/';
  237. #endif
  238. memcpy(rpath + strlen(rpath), ret, strlen(ret));
  239. LLOGI("加载文件 %s", rpath);
  240. if (check_file_path(rpath) == NULL)
  241. return -2;
  242. break;
  243. }
  244. }
  245. }
  246. }
  247. }
  248. }
  249. ret = ptr + 1;
  250. }
  251. ptr++;
  252. }
  253. return 0;
  254. }
  255. typedef struct luac_ctx
  256. {
  257. char *ptr;
  258. size_t len;
  259. } luac_ctx_t;
  260. luac_ctx_t* last_ctx = NULL;
  261. static int writer(lua_State *L, const void *p, size_t size, void *u)
  262. {
  263. UNUSED(L);
  264. // LLOGD("写入部分数据 %p %d", p, size);
  265. luac_ctx_t *ctx = (luac_ctx_t *)u;
  266. if (ctx->ptr == NULL)
  267. {
  268. ctx->ptr = luat_heap_malloc(size);
  269. ctx->len = size;
  270. memcpy(ctx->ptr, p, size);
  271. return 0;
  272. }
  273. char *ptr = luat_heap_realloc(ctx->ptr, ctx->len + size);
  274. if (ptr == NULL)
  275. {
  276. LLOGE("内存分配失败");
  277. return 1;
  278. }
  279. memcpy(ptr + ctx->len, p, size);
  280. ctx->ptr = ptr;
  281. ctx->len += size;
  282. return 0;
  283. }
  284. static int pmain(lua_State *L)
  285. {
  286. const char *name = luaL_checkstring(L, 1);
  287. size_t len = 0;
  288. const char *data = luaL_checklstring(L, 2, &len);
  289. int ret = luaL_loadbufferx(L, data, len, name, NULL);
  290. if (ret)
  291. {
  292. LLOGE("文件加载失败 %s %s", name, lua_tostring(L, -1));
  293. return 0;
  294. }
  295. // LLOGD("luac转换成功,开始转buff %s", name);
  296. luac_ctx_t *ctx = luat_heap_malloc(sizeof(luac_ctx_t));
  297. memset(ctx, 0, sizeof(luac_ctx_t));
  298. // LLOGD("getproto ");
  299. const Proto *f = getproto(L->top - 1);
  300. // LLOGD("Proto %p", f);
  301. if (cfg_luac_strip) {
  302. if (cfg_luac_strip == 1 && !strcmp("main.lua", name)) {
  303. ret = luaU_dump(L, f, writer, ctx, 0);
  304. }
  305. else {
  306. ret = luaU_dump(L, f, writer, ctx, 1);
  307. }
  308. }
  309. else {
  310. ret = luaU_dump(L, f, writer, ctx, 0);
  311. }
  312. // LLOGD("luaU_dump 执行完成");
  313. if (ret == 0)
  314. {
  315. // luadb_addfile(name, ctx->ptr, ctx->len);
  316. luat_luadb2_write(&luadb_ctx, name, ctx->ptr, ctx->len);
  317. luadb_ptr = luadb_ctx.dataptr;
  318. }
  319. lua_pushinteger(L, ret);
  320. luat_heap_free(ctx->ptr);
  321. luat_heap_free(ctx);
  322. return 1;
  323. }
  324. static int to_luac(const char *fullpath, const char *name, char *data, size_t len)
  325. {
  326. // LLOGD("检查语法并转换成luac %s 路径 %s", name, fullpath);
  327. lua_State *L = lua_newstate(luat_heap_alloc, NULL);
  328. // LLOGD("创建临时luavm");
  329. lua_pushcfunction(L, &pmain);
  330. lua_pushstring(L, name);
  331. lua_pushlstring(L, data, len);
  332. // LLOGD("准备执行luac转换");
  333. int ret = lua_pcall(L, 2, 1, 0);
  334. if (ret)
  335. {
  336. LLOGD("lua文件加载失败 %s %d", fullpath, ret);
  337. lua_close(L);
  338. return -1;
  339. }
  340. ret = luaL_checkinteger(L, -1);
  341. lua_close(L);
  342. return ret;
  343. }
  344. static int add_onefile(const char *path)
  345. {
  346. size_t len = 0;
  347. int ret = 0;
  348. // LLOGD("把%s当做main.lua运行", path);
  349. char tmpname[512] = {0};
  350. FILE *f = fopen(path, "rb");
  351. if (!f)
  352. {
  353. LLOGE("文件不存在 %s", path);
  354. return -1;
  355. }
  356. fseek(f, 0, SEEK_END);
  357. len = ftell(f);
  358. fseek(f, 0, SEEK_SET);
  359. // void* fptr = luat_heap_malloc(len);
  360. char *tmp = luat_heap_malloc(len);
  361. if (tmp == NULL)
  362. {
  363. fclose(f);
  364. LLOGE("文件太大,内存放不下 %s", path);
  365. return -2;
  366. }
  367. fread(tmp, 1, len, f);
  368. fclose(f);
  369. for (size_t i = strlen(path); i > 0; i--)
  370. {
  371. if (path[i - 1] == '/' || path[i - 1] == '\\')
  372. {
  373. memcpy(tmpname, path + i, strlen(path) - 1);
  374. break;
  375. }
  376. }
  377. if (tmpname[0] == 0x00)
  378. {
  379. memcpy(tmpname, path, strlen(path));
  380. }
  381. if (!memcmp(path + strlen(path) - 4, ".lua", 4))
  382. {
  383. ret = to_luac(path, tmpname, tmp, len);
  384. }
  385. else
  386. {
  387. // ret = luadb_addfile(tmpname, tmp, len);
  388. ret = luat_luadb2_write(&luadb_ctx, tmpname, tmp, len);
  389. luadb_ptr = luadb_ctx.dataptr;
  390. }
  391. luat_heap_free(tmp);
  392. return ret;
  393. }
  394. void *check_file_path(const char *path)
  395. {
  396. if (strlen(path) < 4 || strlen(path) >= 512)
  397. {
  398. LLOGD("文件长度不对劲 %d %s", strlen(path), path);
  399. return NULL;
  400. }
  401. // 目录模式
  402. if (!memcmp(path + strlen(path) - 1, "/", 1) || !memcmp(path + strlen(path) - 1, "\\", 1))
  403. {
  404. DIR *dp;
  405. struct dirent *ep;
  406. // int index = 0;
  407. char buff[512] = {0};
  408. // LLOGD("加载目录 %s", path);
  409. #ifdef LUA_USE_WINDOWS
  410. memcpy(buff, path, strlen(path));
  411. #else
  412. memcpy(buff, path, strlen(path) - 1);
  413. #endif
  414. dp = opendir(buff);
  415. // LLOGD("目录打开 %p", dp);
  416. if (dp != NULL)
  417. {
  418. // LLOGD("开始遍历目录 %s", path);
  419. while ((ep = readdir(dp)) != NULL)
  420. {
  421. // LLOGD("文件/目录 %s %d", ep->d_name, ep->d_type);
  422. if (ep->d_type != DT_REG)
  423. {
  424. continue;
  425. }
  426. #ifdef LUA_USE_WINDOWS
  427. sprintf(buff, "%s\\%s", path, ep->d_name);
  428. #else
  429. sprintf(buff, "%s/%s", path, ep->d_name);
  430. #endif
  431. if (add_onefile(buff))
  432. {
  433. return NULL;
  434. }
  435. }
  436. // LLOGD("遍历结束");
  437. (void)closedir(dp);
  438. return luadb_ptr;
  439. }
  440. else
  441. {
  442. LLOGW("opendir file %s failed", path);
  443. return NULL;
  444. }
  445. }
  446. else
  447. {
  448. if (add_onefile(path))
  449. {
  450. return NULL;
  451. }
  452. return luadb_ptr;
  453. }
  454. // return NULL;
  455. }
  456. // 加载并分析文件
  457. int luat_cmd_load_and_analyse(const char *path)
  458. {
  459. size_t len = 0;
  460. int ret = 0;
  461. // LLOGD("把%s当做main.lua运行", path);
  462. char tmpname[512] = {0};
  463. FILE *f = fopen(path, "rb");
  464. if (!f)
  465. {
  466. LLOGE("文件不存在 %s", path);
  467. return -1;
  468. }
  469. fseek(f, 0, SEEK_END);
  470. len = ftell(f);
  471. fseek(f, 0, SEEK_SET);
  472. // void* fptr = luat_heap_malloc(len);
  473. char *tmp = luat_heap_malloc(len);
  474. if (tmp == NULL)
  475. {
  476. fclose(f);
  477. LLOGE("文件太大,内存放不下 %s", path);
  478. return -2;
  479. }
  480. fread(tmp, 1, len, f);
  481. fclose(f);
  482. for (size_t i = strlen(path); i > 0; i--)
  483. {
  484. if (path[i - 1] == '/' || path[i - 1] == '\\')
  485. {
  486. memcpy(tmpname, path + i, strlen(path) - 1);
  487. break;
  488. }
  489. }
  490. if (tmpname[0] == 0x00)
  491. {
  492. memcpy(tmpname, path, strlen(path));
  493. }
  494. if (!memcmp(path + strlen(path) - 4, ".lua", 4))
  495. {
  496. ret = to_luac(path, tmpname, tmp, len);
  497. }
  498. else
  499. {
  500. // ret = luadb_addfile(tmpname, tmp, len);
  501. ret = luat_luadb2_write(&luadb_ctx, tmpname, tmp, len);
  502. luadb_ptr = luadb_ctx.dataptr;
  503. }
  504. luat_heap_free(tmp);
  505. return ret;
  506. }