From 75a3b0033e7459a3c6bdec637a1e05515c06ea0a Mon Sep 17 00:00:00 2001 From: TSnake41 Date: Sun, 10 May 2020 13:42:51 +0200 Subject: [PATCH] Improve builder and self-detection. --- src/raylua_builder.c | 21 ++++++++--------- src/raylua_builder.lua | 16 ++++--------- src/raylua_e.c | 36 ++++++++++++----------------- src/raylua_self.c | 52 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 44 deletions(-) create mode 100644 src/raylua_self.c diff --git a/src/raylua_builder.c b/src/raylua_builder.c index 3e8b149..dc52e8e 100644 --- a/src/raylua_builder.c +++ b/src/raylua_builder.c @@ -40,6 +40,8 @@ static void append_file(FILE *dst, FILE *src) { + rewind(src); + size_t count; do { uint8_t buffer[4096]; @@ -55,7 +57,7 @@ typedef struct raylua_builder { static int raylua_builder_new(lua_State *L) { - const char *self_path = luaL_checkstring(L, -2); + FILE *self = lua_touserdata(L, -2); const char *path = luaL_checkstring(L, -1); raylua_builder *builder = malloc(sizeof(raylua_builder)); @@ -69,20 +71,11 @@ static int raylua_builder_new(lua_State *L) builder->file = f; - FILE *self = fopen(self_path, "rb"); - if (!self) { - free(builder); - fclose(f); - return luaL_error(L, "Can't open self (%s)", self_path); - } - append_file(f, self); - fclose(self); if (!mz_zip_writer_init_cfile(&builder->zip, f, 0)) { free(builder); fclose(f); - fclose(self); return luaL_error(L, "Can't initialize miniz writer."); } @@ -170,11 +163,17 @@ static int list_dir(lua_State *L) return 1; } -int raylua_builder_boot(lua_State *L) +int raylua_builder_boot(lua_State *L, FILE *self) { lua_pushcfunction(L, get_type); lua_setglobal(L, "get_type"); + lua_pushlightuserdata(L, append_file); + lua_setglobal(L, "append_file"); + + lua_pushlightuserdata(L, self); + lua_setglobal(L, "self"); + lua_pushcfunction(L, list_dir); lua_setglobal(L, "list_dir"); diff --git a/src/raylua_builder.lua b/src/raylua_builder.lua index 673e53f..9709c74 100644 --- a/src/raylua_builder.lua +++ b/src/raylua_builder.lua @@ -43,8 +43,8 @@ local ffi = require "ffi" ffi.cdef "typedef struct FILE FILE;" +local append_file = ffi.cast("void (*)(FILE *, FILE *)", append_file) -local self_path = arg[0] local input_path = arg[1] print "BUILDER: Initialized builder" @@ -59,12 +59,6 @@ local function path_concat(...) return table.concat({ ... }, "/") end -if ffi.os == "Windows" and self_path:sub("-4") ~= ".exe" then - self_path = self_path .. ".exe" -end - -print("BUILDER: Self is " .. self_path) - if t == "directory" then print "BUILDER: Building from folder." @@ -82,7 +76,7 @@ if t == "directory" then print("BUILDER: Building " .. output) - local builder = builder_new(self_path, output) + local builder = builder_new(self, output) assert(builder, "Can't initialize builder") local have_main = false @@ -145,19 +139,17 @@ elseif t == "file" then print "BUILDER: Building from zip file." local dest = assert(io.open(path, "wb"), "Can't open destination file.") - local source = assert(io.open(self_path, "rb"), "Can't open self file.") local input = assert(io.open(input_path, "rb"), "Can't open zip file.") - append_file(dest, source) + append_file(dest, self) append_file(dest, input) dest:close() - source:close() input:close() elseif ext == ".lua" then print "BUILDER: Building from lua file." - local builder = builder_new(self_path, path) + local builder = builder_new(self, path) builder_add(builder, input_path, "main.lua") builder_close(builder) else diff --git a/src/raylua_e.c b/src/raylua_e.c index 1bb9bf5..376b543 100644 --- a/src/raylua_e.c +++ b/src/raylua_e.c @@ -28,8 +28,10 @@ #include "raylua.h" #include "lib/miniz.h" +FILE *raylua_open_self(const char *argv0); + #ifndef RAYLUA_NO_BUILDER -int raylua_builder_boot(lua_State *L); +int raylua_builder_boot(lua_State *L, FILE *self); #endif static mz_zip_archive zip_file; @@ -140,11 +142,11 @@ char *raylua_loadFileText(const char *path) return buffer; } -static bool raylua_init_payload(const char *path) +static bool raylua_init_payload(FILE *self) { mz_zip_zero_struct(&zip_file); - return mz_zip_reader_init_file(&zip_file, path, 0); + return mz_zip_reader_init_cfile(&zip_file, self, 0, 0); } int main(int argc, const char **argv) @@ -154,7 +156,7 @@ int main(int argc, const char **argv) if (L == NULL) { puts("RAYLUA: Unable to initialize Lua."); - return 0; + return 1; } luaL_openlibs(L); @@ -172,32 +174,24 @@ int main(int argc, const char **argv) lua_setglobal(L, "arg"); - const char *path = argv[0]; - #ifdef WIN32 - /* Executable name translation. */ - size_t path_len = strlen(path); - char new_path[path_len + 5]; - - if (path_len > 4 && stricmp(path + path_len - 4, ".exe")) { - strcpy(new_path, path); - strcpy(new_path + path_len, ".exe"); - - printf("RAYLUA: Translated self executable name from %s to %s.\n", path, new_path); - path = new_path; - } - #endif - SetFilesystemOverride((FilesystemOverride){ .loadFileData = &raylua_loadFileData, .loadFileText = &raylua_loadFileText, }); - if (!raylua_init_payload(path)) { + FILE *self = raylua_open_self(argv[0]); + + if (self == NULL) { + puts("RAYLUA: Can't open self, cannot continue."); + return 1; + } + + if (!raylua_init_payload(self)) { #ifdef RAYLUA_NO_BUILDER puts("RAYLUA: No payload."); #else puts("RAYLUA: No payload, use internal builder."); - raylua_builder_boot(L); + raylua_builder_boot(L, self); #endif } else { /* Boot on payload. */ diff --git a/src/raylua_self.c b/src/raylua_self.c new file mode 100644 index 0000000..324b02d --- /dev/null +++ b/src/raylua_self.c @@ -0,0 +1,52 @@ +/* + Copyright (C) 2020 Astie Teddy + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +/* Procedures to open the current process executable. */ + +#include +#include + +#ifdef WIN32 +#include +#else +#include +#endif + +/* Use platform specific functions. */ +static inline FILE *open_self_platform(void) +{ + #ifdef WIN32 + char path[MAX_PATH + 1]; + memset(path, '\0', sizeof(path)); + + GetModuleFileName(NULL, path, MAX_PATH); + return fopen(path, "rb"); + #elif defined(__linux__) + return fopen("/proc/self/exe", "r"); + #else + /* TODO: Implement for Darwin and BSD hosts. */ + return NULL; /* fallback to argv0 */ + #endif +} + +FILE *raylua_open_self(const char *argv0) +{ + FILE *self = open_self_platform(); + + if (self == NULL) + self = fopen(argv0, "rb"); + + return self; +}