Skip to content

Commit 2f58a40

Browse files
committed
extract program files
1 parent f279f50 commit 2f58a40

File tree

2 files changed

+157
-6
lines changed

2 files changed

+157
-6
lines changed

core/src/xmake/engine.c

+156-5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@
5050
# include <image.h>
5151
#endif
5252

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+
5364
/* //////////////////////////////////////////////////////////////////////////////////////
5465
* macros
5566
*/
@@ -81,6 +92,11 @@ typedef struct __xm_engine_t
8192
// the engine name
8293
tb_char_t name[64];
8394

95+
#ifdef XM_EMBED_ENABLE
96+
// the temporary directory
97+
tb_char_t tmpdir[TB_PATH_MAXN];
98+
#endif
99+
84100
}xm_engine_t;
85101

86102
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -744,16 +760,42 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
744760
return ok;
745761
}
746762

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+
747782
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)
748783
{
749784
// check
750785
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
751786

752787
tb_bool_t ok = tb_false;
788+
tb_char_t data[TB_PATH_MAXN] = {0};
753789
do
754790
{
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+
755798
// get it from the environment variable first
756-
tb_char_t data[TB_PATH_MAXN] = {0};
757799
if (tb_environment_first("XMAKE_PROGRAM_DIR", data, sizeof(data)) && tb_path_absolute(data, path, maxn))
758800
{
759801
ok = tb_true;
@@ -1097,6 +1139,109 @@ static tb_pointer_t xm_engine_lua_realloc(tb_pointer_t udata, tb_pointer_t data,
10971139
}
10981140
#endif
10991141

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+
11001245
/* //////////////////////////////////////////////////////////////////////////////////////
11011246
* implementation
11021247
*/
@@ -1215,6 +1360,12 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
12151360
lua_pushstring(engine->lua, version_cstr);
12161361
lua_setglobal(engine->lua, "_VERSION");
12171362

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+
12181369
// init short version string
12191370
tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u", version->major, version->minor, version->alter);
12201371
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
13061457
// get the program directory
13071458
if (!xm_engine_get_program_directory(engine, path, sizeof(path), path)) return -1;
13081459

1460+
#ifdef XM_EMBED_ENABLE
1461+
if (!xm_engine_extract_programfiles(engine, path)) return -1;
1462+
#endif
1463+
13091464
// append the main script path
13101465
tb_strcat(path, "/core/_xmake_main.lua");
13111466

@@ -1338,10 +1493,6 @@ tb_int_t xm_engine_main(xm_engine_ref_t self, tb_int_t argc, tb_char_t** argv, t
13381493
return -1;
13391494
}
13401495

1341-
#ifdef XM_EMBED_ENABLE
1342-
tb_trace_i("g_xmake_xmz_data: %p", g_xmake_xmz_data);
1343-
#endif
1344-
13451496
// get the error code
13461497
return (tb_int_t)lua_tonumber(engine->lua, -1);
13471498
}

xmake/modules/utils/archive/archive_xmz.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function _archive_files(archivefile, inputfiles, opt)
3333
filepath = path.relative(filepath, curdir)
3434
end
3535
outputfile:write(bytes(2):u16be_set(1, #filepath))
36-
outputfile:write(inputfile)
36+
outputfile:write(filepath)
3737
local data = io.readfile(inputfile, {encoding = "binary"})
3838
vprint("archiving %s, %d bytes", inputfile, data and #data or 0)
3939
outputfile:write(bytes(4):u32be_set(1, #data))

0 commit comments

Comments
 (0)