From 479fec64ec7924b2bdc4708561621d589a1c0922 Mon Sep 17 00:00:00 2001
From: Alexander Turenko <alexander.turenko@tarantool.org>
Date: Wed, 15 Feb 2023 22:01:14 +0300
Subject: [PATCH] lua: add minifio.script() to get main script path

To be used in loaders, see the next commit.

While I'm here, actualized `tarantool_lua_init()` description.

Follows up #7774
Part of #8182

NO_DOC=for internal use
NO_CHANGELOG=see NO_DOC
NO_TEST=see NO_DOC
---
 src/lua/init.c      |  4 +++-
 src/lua/init.h      | 11 +++--------
 src/lua/minifio.c   | 40 ++++++++++++++++++++++++++++++++++++++++
 src/lua/minifio.h   |  6 ++++++
 src/lua/minifio.lua |  6 +++++-
 src/main.cc         |  2 +-
 6 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/src/lua/init.c b/src/lua/init.c
index eb5d47f334..191447c63b 100644
--- a/src/lua/init.c
+++ b/src/lua/init.c
@@ -835,7 +835,8 @@ luaT_set_module_from_source(struct lua_State *L, const char *modname,
 }
 
 void
-tarantool_lua_init(const char *tarantool_bin, int argc, char **argv)
+tarantool_lua_init(const char *tarantool_bin, const char *script, int argc,
+		   char **argv)
 {
 	lua_State *L = luaL_newstate();
 	if (L == NULL) {
@@ -872,6 +873,7 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv)
 	 */
 	tarantool_lua_setpaths(L);
 	tarantool_lua_minifio_init(L);
+	minifio_set_script(script);
 	luaT_set_module_from_source(L, "internal.minifio", minifio_lua);
 	luaT_set_module_from_source(L, "internal.loaders", loaders_lua);
 
diff --git a/src/lua/init.h b/src/lua/init.h
index 2ce2030a3e..c4d65b6fd1 100644
--- a/src/lua/init.h
+++ b/src/lua/init.h
@@ -47,16 +47,11 @@ extern struct lua_State *tarantool_L;
 #define O_BYTECODE    0x2
 
 /**
- * Create an instance of Lua interpreter and load it with
- * Tarantool modules.  Creates a Lua state, imports global
- * Tarantool modules, then calls box_lua_init(), which performs
- * module-specific imports. The created state can be freed as any
- * other, with lua_close().
- *
- * @return  L on success, 0 if out of memory
+ * Create tarantool_L and initialize built-in Lua modules.
  */
 void
-tarantool_lua_init(const char *tarantool_bin, int argc, char **argv);
+tarantool_lua_init(const char *tarantool_bin, const char *script, int argc,
+		   char **argv);
 
 /** Free Lua subsystem resources. */
 void
diff --git a/src/lua/minifio.c b/src/lua/minifio.c
index 7795408a84..5658e29676 100644
--- a/src/lua/minifio.c
+++ b/src/lua/minifio.c
@@ -5,14 +5,31 @@
  */
 #include "lua/minifio.h"
 
+#include <string.h>
 #include <unistd.h>
 #include <lua.h>
 #include <lauxlib.h>
 
+#include "trivia/util.h"
 #include "diag.h"
 #include "lua/utils.h"
 #include "lua/error.h"
 
+static char *main_script = NULL;
+
+void
+minifio_set_script(const char *script)
+{
+	if (script == NULL) {
+		free(main_script);
+		main_script = NULL;
+		return;
+	}
+	size_t len = strlen(script);
+	main_script = xrealloc(main_script, len + 1);
+	memcpy(main_script, script, len + 1);
+}
+
 /**
  * Push nil and an error with strerror() based message.
  */
@@ -45,11 +62,34 @@ lbox_minifio_cwd(struct lua_State *L)
 	return 1;
 }
 
+/**
+ * minifio.script() -- get path of the main script.
+ *
+ * Important: the path is returned verbatim as provided in the
+ * process'es arguments and should be interpreted relatively to
+ * current working directory *at tarantool startup*.
+ *
+ * The current working directory may be changed later and it'll
+ * make the path value invalid. Note that the directory may be
+ * changed implicitly by calling box.cfg().
+ */
+static int
+lbox_minifio_script(struct lua_State *L)
+{
+	if (main_script == NULL) {
+		lua_pushnil(L);
+		return 1;
+	}
+	lua_pushstring(L, main_script);
+	return 1;
+}
+
 void
 tarantool_lua_minifio_init(struct lua_State *L)
 {
 	static const struct luaL_Reg minifio_methods[] = {
 		{"cwd", lbox_minifio_cwd},
+		{"script", lbox_minifio_script},
 		{NULL, NULL}
 	};
 
diff --git a/src/lua/minifio.h b/src/lua/minifio.h
index 873871baaa..a0c2c23de8 100644
--- a/src/lua/minifio.h
+++ b/src/lua/minifio.h
@@ -11,6 +11,12 @@ extern "C" {
 
 struct lua_State;
 
+/**
+ * Set path to the main script.
+ */
+void
+minifio_set_script(const char *script);
+
 void
 tarantool_lua_minifio_init(struct lua_State *L);
 
diff --git a/src/lua/minifio.lua b/src/lua/minifio.lua
index 960661f8bc..20ef570955 100644
--- a/src/lua/minifio.lua
+++ b/src/lua/minifio.lua
@@ -12,7 +12,11 @@ ffi.cdef([[
 
 -- {{{ Functions exposed by fio
 
--- NB: minifio.cwd() is defined in src/lua/minifio.c.
+-- Several functions are defined in src/lua/minifio.c.
+--
+-- List them to ease searching by a function name.
+assert(type(minifio.cwd) == 'function')
+assert(type(minifio.script) == 'function')
 
 function minifio.pathjoin(...)
     local i, path = 1, nil
diff --git a/src/main.cc b/src/main.cc
index 048cf6c93f..e8fe3d6657 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -797,7 +797,7 @@ main(int argc, char **argv)
 #ifndef NDEBUG
 	errinj_set_with_environment_vars();
 #endif
-	tarantool_lua_init(tarantool_bin, main_argc, main_argv);
+	tarantool_lua_init(tarantool_bin, script, main_argc, main_argv);
 
 	start_time = ev_monotonic_time();
 
-- 
GitLab