@@ -204,27 +204,35 @@ static void lua_report_exception(lua_State *L)
} while (*s++);
}
-int run_lua_script(lua_State *L, const char *script, const char *function, char *parms)
+int run_lua_script(lua_State *L, const char *script, bool load, const char *function, char *parms)
{
int ret;
const char *output;
- if (!function || !L)
+ if (!L) {
+ ERROR("Lua script must be executed, but no valid Lua state was set");
return -EINVAL;
+ }
- if (script) {
+ if (load) {
+ TRACE("Loading Lua %s script", script);
if (luaL_loadfile(L, script)) {
ERROR("ERROR loading %s", script);
return -1;
}
+
+ ret = lua_pcall(L, 0, 0, 0);
+ if (ret) {
+ LUAstackDump(L);
+ ERROR("ERROR preparing Lua script %s %d",
+ script, ret);
+ return -1;
+ }
}
- ret = lua_pcall(L, 0, 0, 0);
- if (ret) {
- LUAstackDump(L);
- ERROR("ERROR preparing Lua script %s %d",
- script, ret);
- return -1;
+ if (!function) {
+ WARN("Script was loaded, no function was set to be executed !");
+ return 0;
}
lua_getglobal(L, function);
@@ -24,10 +24,21 @@
static void lua_handler(void);
+struct fn_names {
+ const char *property_name; /* Name of property in sw-description */
+ const char *def_fn; /* Default name function if property is not set */
+};
+
+const struct fn_names fn_property_names[] = {
+ [PREINSTALL] = {"preinstall", "preinst"},
+ [POSTINSTALL] = {"postinstall", "postinst"},
+ [POSTFAILURE] = {"postfailure", "postfailure"}
+};
+
static int start_lua_script(struct img_type *img, void *data)
{
int ret;
- const char *fnname;
+ const char *fnname = NULL;
struct script_handler_data *script_data;
lua_State *L;
const char* tmp = get_tmpdirscripts();
@@ -36,8 +47,29 @@ static int start_lua_script(struct img_type *img, void *data)
if (!data)
return -1;
+ script_data = data;
+
+ /*
+ * A little paranoid, thios shouln't happen
+ */
+ if (script_data->scriptfn < PREINSTALL || script_data->scriptfn > POSTFAILURE)
+ return -EINVAL;
+
bool global = strtobool(dict_get_value(&img->properties, "global-state"));
+ /*
+ * Note: if global is set, functions should be unique
+ * The name of function should be set inside the script
+ */
+ fnname = dict_get_value(&img->properties, fn_property_names[script_data->scriptfn].property_name);
+
+ if (!fnname && !global) {
+ fnname = fn_property_names[script_data->scriptfn].def_fn;
+ }
+
+ /*
+ * Assign the Lua state
+ */
if (global) {
TRACE("Executing with global state");
L = img->L;
@@ -50,34 +82,51 @@ static int start_lua_script(struct img_type *img, void *data)
return -1;
}
- script_data = data;
+ /*
+ * In case of global, loads the script just once. Check if a function is already
+ * present. An Overwrite is excluded by design. All functions should be unique.
+ */
- switch (script_data->scriptfn) {
- case PREINSTALL:
- fnname = dict_get_value(&img->properties, "preinstall");
- if (!fnname)
- fnname="preinst";
- break;
- case POSTINSTALL:
- fnname = dict_get_value(&img->properties, "postinstall");
- if (!fnname)
- fnname="postinst";
- break;
- case POSTFAILURE:
- fnname = dict_get_value(&img->properties, "postfailure");
- if (!fnname)
- fnname="postfailure";
- break;
- default:
- /* no error, simply no call */
- return 0;
+ bool load_script = true;
+
+ if (global) {
+ if (script_data->scriptfn == PREINSTALL) {
+ for (int i = PREINSTALL; i <= POSTINSTALL; i++) {
+ const char *fn = fn_property_names[script_data->scriptfn].property_name;
+ if (!fn)
+ continue;
+ lua_getglobal(L, fn);
+ if(lua_isfunction(L,lua_gettop(L))) {
+ ERROR("Function %s already defined, functions must be unique", fn);
+ return -1;
+ }
+ }
+ } else {
+ /*
+ * Script was already loaded, skip it
+ */
+ load_script = false;
+ }
}
+ /*
+ * Trace what should be done
+ */
snprintf(filename, sizeof(filename),
"%s%s", tmp, img->fname);
- TRACE("Calling Lua %s with %s", filename, fnname);
+ TRACE("%s: Calling Lua %s with %s",
+ fn_property_names[script_data->scriptfn].property_name,
+ filename,
+ fnname ? fnname : "no function, just loaded");
+
+ /*
+ * In case no function is selected and we run in global,
+ * script was already loaded and there is nothing to do
+ */
+ if (global && !fnname && !load_script)
+ return 0;
- ret = run_lua_script(L, filename, fnname, img->type_data);
+ ret = run_lua_script(L, filename, load_script, fnname, img->type_data);
if (!global)
lua_close(L);
@@ -20,7 +20,7 @@ typedef enum {
} root_dev_type;
void LUAstackDump (lua_State *L);
-int run_lua_script(lua_State *L, const char *script, const char *function, char *parms);
+int run_lua_script(lua_State *L, const char *script, bool load, const char *function, char *parms);
lua_State *lua_init(struct dict *bootenv);
int lua_load_buffer(lua_State *L, const char *buf);
int lua_parser_fn(lua_State *L, const char *fcn, struct img_type *img);
Up now, scripts have run in isolated context: SWUpdate allocates a new Lua state, and import the basic libraries before loading the script. A script is then isolated, but it cannot access to function already loaded, or it is not possible to reuse functions from 2 or more scripts. With the introduction of a per installation Lua state, Lua scripts can call functions already defined in previous scripts, or defined in sw-description. Because when a script is loaded, it could overwrite existing functions with the same name, it was decided that functions in scripts must be unique, that is each function should be declared just once during an installation process. This means that for global state, sw-description should contain the name of the function for each step (pre- , postinstall or postfailure) that should be called: the names preinst, postinst and postfailure are still valid in case the script runs with isolated state. This allows also to load a script without executing if no functions are defined, and functions in the script can be called by later scripts. Note that the handler will load the script in case of global state just once during the "preinstall" call. Later, it is assumed that functions will be already available. Signed-off-by: Stefano Babic <stefano.babic@swupdate.org> --- corelib/lua_interface.c | 26 ++++++---- handlers/lua_scripthandler.c | 95 +++++++++++++++++++++++++++--------- include/lua_util.h | 2 +- 3 files changed, 90 insertions(+), 33 deletions(-) -- 2.34.1