summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-08-22 22:37:49 +0800
committerruki <[email protected]>2024-08-22 22:37:49 +0800
commit2f58a40660f680e9b54c7d747e962b6c283613ba (patch)
tree591013c074181b37373d65c77ae09f371c2d062c
parentf279f505880fc1c7390a67b445c2a934fcb04302 (diff)
extract program files
-rw-r--r--core/src/xmake/engine.c161
-rw-r--r--xmake/modules/utils/archive/archive_xmz.lua2
2 files changed, 157 insertions, 6 deletions
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c
index 2197867f1..71a997881 100644
--- a/core/src/xmake/engine.c
+++ b/core/src/xmake/engine.c
@@ -50,6 +50,17 @@
# include <image.h>
#endif
+// for uid
+#ifndef TB_CONFIG_OS_WINDOWS
+# include <unistd.h>
+# include <errno.h>
+#endif
+
+// for embed files
+#ifdef XM_EMBED_ENABLE
+# include "lz4/prefix.h"
+#endif
+
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
@@ -81,6 +92,11 @@ typedef struct __xm_engine_t
// the engine name
tb_char_t name[64];
+#ifdef XM_EMBED_ENABLE
+ // the temporary directory
+ tb_char_t tmpdir[TB_PATH_MAXN];
+#endif
+
}xm_engine_t;
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -744,16 +760,42 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
return ok;
}
+#ifdef XM_EMBED_ENABLE
+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)
+{
+ tb_char_t data[TB_PATH_MAXN] = {0};
+ if (tb_directory_temporary(data, sizeof(data)))
+ {
+ // get euid
+ tb_int_t euid = 0;
+#ifndef TB_CONFIG_OS_WINDOWS
+ euid = geteuid();
+#endif
+
+ tb_snprintf(path, maxn, "%s/.%s%d/%s", data, name, euid, version_cstr);
+ return tb_true;
+ }
+ return tb_false;
+}
+#endif
+
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)
{
// check
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
tb_bool_t ok = tb_false;
+ tb_char_t data[TB_PATH_MAXN] = {0};
do
{
+#ifdef XM_EMBED_ENABLE
+ // get it from the temporary directory
+ tb_strlcpy(path, engine->tmpdir, maxn);
+ ok = tb_true;
+ break;
+#endif
+
// get it from the environment variable first
- tb_char_t data[TB_PATH_MAXN] = {0};
if (tb_environment_first("XMAKE_PROGRAM_DIR", data, sizeof(data)) && tb_path_absolute(data, path, maxn))
{
ok = tb_true;
@@ -1097,6 +1139,109 @@ static tb_pointer_t xm_engine_lua_realloc(tb_pointer_t udata, tb_pointer_t data,
}
#endif
+#ifdef XM_EMBED_ENABLE
+static tb_bool_t xm_engine_extract_programfiles(xm_engine_t* engine, tb_char_t const* programdir)
+{
+ tb_file_info_t info = {0};
+ if (tb_file_info(programdir, &info)) return tb_true;
+
+ tb_byte_t const* data = g_xmake_xmz_data;
+ tb_size_t size = sizeof(g_xmake_xmz_data);
+
+ // do decompress
+ tb_bool_t ok = tb_false;
+ LZ4F_errorCode_t code;
+ LZ4F_decompressionContext_t ctx = tb_null;
+ tb_buffer_t result;
+ do
+ {
+ tb_buffer_init(&result);
+
+ code = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
+ if (LZ4F_isError(code)) break;
+
+ tb_byte_t buffer[8192];
+ tb_bool_t failed = tb_false;
+ while (1)
+ {
+ size_t advance = (size_t)size;
+ size_t buffer_size = sizeof(buffer);
+ code = LZ4F_decompress(ctx, buffer, &buffer_size, data, &advance, tb_null);
+ if (LZ4F_isError(code))
+ {
+ failed = tb_true;
+ break;
+ }
+
+ if (buffer_size == 0) break;
+ data += advance;
+ size -= advance;
+
+ tb_buffer_memncat(&result, buffer, buffer_size);
+ }
+ tb_assert_and_check_break(!failed && tb_buffer_size(&result));
+
+ ok = tb_true;
+ } while (0);
+
+ // extract files to programdir
+ if (ok)
+ {
+ data = tb_buffer_data(&result);
+ size = tb_buffer_size(&result);
+ tb_byte_t const* p = data;
+ tb_byte_t const* e = data + size;
+ tb_size_t n = 0;
+ tb_char_t filepath[TB_PATH_MAXN];
+ tb_int_t pos = tb_snprintf(filepath, sizeof(filepath), "%s/", programdir);
+ while (p < e)
+ {
+ // get filepath
+ n = (tb_size_t)tb_bits_get_u16_be(p);
+ p += 2;
+ tb_assert_and_check_break(pos + n + 1 < sizeof(filepath));
+ tb_strncpy(filepath + pos, (tb_char_t const*)p, n);
+ filepath[pos + n] = '\0';
+ p += n;
+
+ // get filedata
+ n = (tb_size_t)tb_bits_get_u32_be(p);
+ p += 4;
+
+ // write file
+ tb_trace_d("extracting %s, %lu bytes ..", filepath, n);
+ tb_stream_ref_t stream = tb_stream_init_from_file(filepath, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
+ tb_assert_and_check_break(stream);
+
+ if (tb_stream_open(stream))
+ {
+ tb_stream_bwrit(stream, p, n);
+ tb_stream_exit(stream);
+ }
+
+ p += n;
+ }
+ ok = (p == e);
+ if (!ok)
+ {
+ tb_trace_e("extract program files failed");
+ }
+ }
+ else
+ {
+ tb_trace_e("decompress program files failed, %s", LZ4F_getErrorName(code));
+ }
+
+ if (ctx)
+ {
+ LZ4F_freeDecompressionContext(ctx);
+ ctx = tb_null;
+ }
+ tb_buffer_exit(&result);
+ return ok;
+}
+#endif
+
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
@@ -1215,6 +1360,12 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
lua_pushstring(engine->lua, version_cstr);
lua_setglobal(engine->lua, "_VERSION");
+#ifdef XM_EMBED_ENABLE
+ // init the temporary directory
+ if (!xm_engine_get_temporary_directory(engine->tmpdir, sizeof(engine->tmpdir), name, version_cstr))
+ break;
+#endif
+
// init short version string
tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u", version->major, version->minor, version->alter);
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
// get the program directory
if (!xm_engine_get_program_directory(engine, path, sizeof(path), path)) return -1;
+#ifdef XM_EMBED_ENABLE
+ if (!xm_engine_extract_programfiles(engine, path)) return -1;
+#endif
+
// append the main script path
tb_strcat(path, "/core/_xmake_main.lua");
@@ -1338,10 +1493,6 @@ tb_int_t xm_engine_main(xm_engine_ref_t self, tb_int_t argc, tb_char_t** argv, t
return -1;
}
-#ifdef XM_EMBED_ENABLE
- tb_trace_i("g_xmake_xmz_data: %p", g_xmake_xmz_data);
-#endif
-
// get the error code
return (tb_int_t)lua_tonumber(engine->lua, -1);
}
diff --git a/xmake/modules/utils/archive/archive_xmz.lua b/xmake/modules/utils/archive/archive_xmz.lua
index 7f4425578..74ccc4c92 100644
--- a/xmake/modules/utils/archive/archive_xmz.lua
+++ b/xmake/modules/utils/archive/archive_xmz.lua
@@ -33,7 +33,7 @@ function _archive_files(archivefile, inputfiles, opt)
filepath = path.relative(filepath, curdir)
end
outputfile:write(bytes(2):u16be_set(1, #filepath))
- outputfile:write(inputfile)
+ outputfile:write(filepath)
local data = io.readfile(inputfile, {encoding = "binary"})
vprint("archiving %s, %d bytes", inputfile, data and #data or 0)
outputfile:write(bytes(4):u32be_set(1, #data))