|
50 | 50 | # include <image.h>
|
51 | 51 | #endif
|
52 | 52 |
|
| 53 | +// for uid |
| 54 | +#ifndef TB_CONFIG_OS_WINDOWS |
| 55 | +# include <unistd.h> |
| 56 | +# include <errno.h> |
| 57 | +#endif |
| 58 | + |
| 59 | +// for embed files |
| 60 | +#ifdef XM_EMBED_ENABLE |
| 61 | +# include "lz4/prefix.h" |
| 62 | +#endif |
| 63 | + |
53 | 64 | /* //////////////////////////////////////////////////////////////////////////////////////
|
54 | 65 | * macros
|
55 | 66 | */
|
@@ -81,6 +92,11 @@ typedef struct __xm_engine_t
|
81 | 92 | // the engine name
|
82 | 93 | tb_char_t name[64];
|
83 | 94 |
|
| 95 | +#ifdef XM_EMBED_ENABLE |
| 96 | + // the temporary directory |
| 97 | + tb_char_t tmpdir[TB_PATH_MAXN]; |
| 98 | +#endif |
| 99 | + |
84 | 100 | }xm_engine_t;
|
85 | 101 |
|
86 | 102 | /* //////////////////////////////////////////////////////////////////////////////////////
|
@@ -744,16 +760,42 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
|
744 | 760 | return ok;
|
745 | 761 | }
|
746 | 762 |
|
| 763 | +#ifdef XM_EMBED_ENABLE |
| 764 | +static tb_bool_t xm_engine_get_temporary_directory(tb_char_t* path, tb_size_t maxn, tb_char_t const* name, tb_char_t const* version_cstr) |
| 765 | +{ |
| 766 | + tb_char_t data[TB_PATH_MAXN] = {0}; |
| 767 | + if (tb_directory_temporary(data, sizeof(data))) |
| 768 | + { |
| 769 | + // get euid |
| 770 | + tb_int_t euid = 0; |
| 771 | +#ifndef TB_CONFIG_OS_WINDOWS |
| 772 | + euid = geteuid(); |
| 773 | +#endif |
| 774 | + |
| 775 | + tb_snprintf(path, maxn, "%s/.%s%d/%s", data, name, euid, version_cstr); |
| 776 | + return tb_true; |
| 777 | + } |
| 778 | + return tb_false; |
| 779 | +} |
| 780 | +#endif |
| 781 | + |
747 | 782 | static tb_bool_t xm_engine_get_program_directory(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn, tb_char_t const* programfile)
|
748 | 783 | {
|
749 | 784 | // check
|
750 | 785 | tb_assert_and_check_return_val(engine && path && maxn, tb_false);
|
751 | 786 |
|
752 | 787 | tb_bool_t ok = tb_false;
|
| 788 | + tb_char_t data[TB_PATH_MAXN] = {0}; |
753 | 789 | do
|
754 | 790 | {
|
| 791 | +#ifdef XM_EMBED_ENABLE |
| 792 | + // get it from the temporary directory |
| 793 | + tb_strlcpy(path, engine->tmpdir, maxn); |
| 794 | + ok = tb_true; |
| 795 | + break; |
| 796 | +#endif |
| 797 | + |
755 | 798 | // get it from the environment variable first
|
756 |
| - tb_char_t data[TB_PATH_MAXN] = {0}; |
757 | 799 | if (tb_environment_first("XMAKE_PROGRAM_DIR", data, sizeof(data)) && tb_path_absolute(data, path, maxn))
|
758 | 800 | {
|
759 | 801 | ok = tb_true;
|
@@ -1097,6 +1139,109 @@ static tb_pointer_t xm_engine_lua_realloc(tb_pointer_t udata, tb_pointer_t data,
|
1097 | 1139 | }
|
1098 | 1140 | #endif
|
1099 | 1141 |
|
| 1142 | +#ifdef XM_EMBED_ENABLE |
| 1143 | +static tb_bool_t xm_engine_extract_programfiles(xm_engine_t* engine, tb_char_t const* programdir) |
| 1144 | +{ |
| 1145 | + tb_file_info_t info = {0}; |
| 1146 | + if (tb_file_info(programdir, &info)) return tb_true; |
| 1147 | + |
| 1148 | + tb_byte_t const* data = g_xmake_xmz_data; |
| 1149 | + tb_size_t size = sizeof(g_xmake_xmz_data); |
| 1150 | + |
| 1151 | + // do decompress |
| 1152 | + tb_bool_t ok = tb_false; |
| 1153 | + LZ4F_errorCode_t code; |
| 1154 | + LZ4F_decompressionContext_t ctx = tb_null; |
| 1155 | + tb_buffer_t result; |
| 1156 | + do |
| 1157 | + { |
| 1158 | + tb_buffer_init(&result); |
| 1159 | + |
| 1160 | + code = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); |
| 1161 | + if (LZ4F_isError(code)) break; |
| 1162 | + |
| 1163 | + tb_byte_t buffer[8192]; |
| 1164 | + tb_bool_t failed = tb_false; |
| 1165 | + while (1) |
| 1166 | + { |
| 1167 | + size_t advance = (size_t)size; |
| 1168 | + size_t buffer_size = sizeof(buffer); |
| 1169 | + code = LZ4F_decompress(ctx, buffer, &buffer_size, data, &advance, tb_null); |
| 1170 | + if (LZ4F_isError(code)) |
| 1171 | + { |
| 1172 | + failed = tb_true; |
| 1173 | + break; |
| 1174 | + } |
| 1175 | + |
| 1176 | + if (buffer_size == 0) break; |
| 1177 | + data += advance; |
| 1178 | + size -= advance; |
| 1179 | + |
| 1180 | + tb_buffer_memncat(&result, buffer, buffer_size); |
| 1181 | + } |
| 1182 | + tb_assert_and_check_break(!failed && tb_buffer_size(&result)); |
| 1183 | + |
| 1184 | + ok = tb_true; |
| 1185 | + } while (0); |
| 1186 | + |
| 1187 | + // extract files to programdir |
| 1188 | + if (ok) |
| 1189 | + { |
| 1190 | + data = tb_buffer_data(&result); |
| 1191 | + size = tb_buffer_size(&result); |
| 1192 | + tb_byte_t const* p = data; |
| 1193 | + tb_byte_t const* e = data + size; |
| 1194 | + tb_size_t n = 0; |
| 1195 | + tb_char_t filepath[TB_PATH_MAXN]; |
| 1196 | + tb_int_t pos = tb_snprintf(filepath, sizeof(filepath), "%s/", programdir); |
| 1197 | + while (p < e) |
| 1198 | + { |
| 1199 | + // get filepath |
| 1200 | + n = (tb_size_t)tb_bits_get_u16_be(p); |
| 1201 | + p += 2; |
| 1202 | + tb_assert_and_check_break(pos + n + 1 < sizeof(filepath)); |
| 1203 | + tb_strncpy(filepath + pos, (tb_char_t const*)p, n); |
| 1204 | + filepath[pos + n] = '\0'; |
| 1205 | + p += n; |
| 1206 | + |
| 1207 | + // get filedata |
| 1208 | + n = (tb_size_t)tb_bits_get_u32_be(p); |
| 1209 | + p += 4; |
| 1210 | + |
| 1211 | + // write file |
| 1212 | + tb_trace_d("extracting %s, %lu bytes ..", filepath, n); |
| 1213 | + tb_stream_ref_t stream = tb_stream_init_from_file(filepath, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); |
| 1214 | + tb_assert_and_check_break(stream); |
| 1215 | + |
| 1216 | + if (tb_stream_open(stream)) |
| 1217 | + { |
| 1218 | + tb_stream_bwrit(stream, p, n); |
| 1219 | + tb_stream_exit(stream); |
| 1220 | + } |
| 1221 | + |
| 1222 | + p += n; |
| 1223 | + } |
| 1224 | + ok = (p == e); |
| 1225 | + if (!ok) |
| 1226 | + { |
| 1227 | + tb_trace_e("extract program files failed"); |
| 1228 | + } |
| 1229 | + } |
| 1230 | + else |
| 1231 | + { |
| 1232 | + tb_trace_e("decompress program files failed, %s", LZ4F_getErrorName(code)); |
| 1233 | + } |
| 1234 | + |
| 1235 | + if (ctx) |
| 1236 | + { |
| 1237 | + LZ4F_freeDecompressionContext(ctx); |
| 1238 | + ctx = tb_null; |
| 1239 | + } |
| 1240 | + tb_buffer_exit(&result); |
| 1241 | + return ok; |
| 1242 | +} |
| 1243 | +#endif |
| 1244 | + |
1100 | 1245 | /* //////////////////////////////////////////////////////////////////////////////////////
|
1101 | 1246 | * implementation
|
1102 | 1247 | */
|
@@ -1215,6 +1360,12 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
|
1215 | 1360 | lua_pushstring(engine->lua, version_cstr);
|
1216 | 1361 | lua_setglobal(engine->lua, "_VERSION");
|
1217 | 1362 |
|
| 1363 | +#ifdef XM_EMBED_ENABLE |
| 1364 | + // init the temporary directory |
| 1365 | + if (!xm_engine_get_temporary_directory(engine->tmpdir, sizeof(engine->tmpdir), name, version_cstr)) |
| 1366 | + break; |
| 1367 | +#endif |
| 1368 | + |
1218 | 1369 | // init short version string
|
1219 | 1370 | tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u", version->major, version->minor, version->alter);
|
1220 | 1371 | lua_pushstring(engine->lua, version_cstr);
|
@@ -1306,6 +1457,10 @@ tb_int_t xm_engine_main(xm_engine_ref_t self, tb_int_t argc, tb_char_t** argv, t
|
1306 | 1457 | // get the program directory
|
1307 | 1458 | if (!xm_engine_get_program_directory(engine, path, sizeof(path), path)) return -1;
|
1308 | 1459 |
|
| 1460 | +#ifdef XM_EMBED_ENABLE |
| 1461 | + if (!xm_engine_extract_programfiles(engine, path)) return -1; |
| 1462 | +#endif |
| 1463 | + |
1309 | 1464 | // append the main script path
|
1310 | 1465 | tb_strcat(path, "/core/_xmake_main.lua");
|
1311 | 1466 |
|
@@ -1338,10 +1493,6 @@ tb_int_t xm_engine_main(xm_engine_ref_t self, tb_int_t argc, tb_char_t** argv, t
|
1338 | 1493 | return -1;
|
1339 | 1494 | }
|
1340 | 1495 |
|
1341 |
| -#ifdef XM_EMBED_ENABLE |
1342 |
| - tb_trace_i("g_xmake_xmz_data: %p", g_xmake_xmz_data); |
1343 |
| -#endif |
1344 |
| - |
1345 | 1496 | // get the error code
|
1346 | 1497 | return (tb_int_t)lua_tonumber(engine->lua, -1);
|
1347 | 1498 | }
|
|
0 commit comments