diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2681af9..12f0a3b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ build: before_script: - apt update - apt -y install libsystemd0 libsystemd-dev - - apt -y install cmake lua-unit libmxml1 libmxml-dev lua-compat53-dev + - apt -y install cmake lua-unit lua-expat lua-compat53-dev - apt -y install luajit libluajit-5.1-dev - apt -y install lua5.1 liblua5.1-dev - apt -y install lua5.2 liblua5.2-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a8de1a..56960de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,6 @@ include(GNUInstallDirs) find_package(PkgConfig REQUIRED) pkg_check_modules(SYSTEMD REQUIRED libsystemd>=242) -pkg_check_modules(MXML REQUIRED mxml) set(CONFIG_LUA_VER "" CACHE STRING "build for exact Lua version") @@ -38,7 +37,7 @@ if( "${LUA_VER}" STREQUAL "5.1" OR "${LUA_VER}" STREQUAL "5.2" ) cmake_path(GET COMPAT53 PARENT_PATH COMPAT53_DIR) endif() -set(LSDBUS_SRCS src/lsdbus.c src/message.c src/introspect.c src/evl.c src/vtab.c) +set(LSDBUS_SRCS src/lsdbus.c src/message.c src/evl.c src/vtab.c) set(LSDBUS_INST_DIR ${CMAKE_INSTALL_PREFIX}/lib/lua/${LUA_VER}/lsdbus/) @@ -47,7 +46,7 @@ add_library(core SHARED ${LSDBUS_SRCS}) target_compile_options(core PRIVATE -Wall -Wextra) target_compile_definitions(core PRIVATE LIBSYSTEMD_VERSION=${SYSTEMD_VERSION}) target_include_directories(core PRIVATE ${LUA_INCLUDE_DIRS} ${COMPAT53_DIR}) -target_link_libraries(core ${SYSTEMD_LIBRARIES} ${MXML_LIBRARIES} ) +target_link_libraries(core ${SYSTEMD_LIBRARIES}) set_target_properties(core PROPERTIES PREFIX "") install(TARGETS core LIBRARY DESTINATION ${LSDBUS_INST_DIR}) diff --git a/README.md b/README.md index 86af174..ff56e9a 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ and sd-event APIs. First, ensure that the correct packages are installed. For example: ```sh -$ sudo apt-get install cmake lua5.3 liblua5.3-dev libsystemd-dev libmxml-dev +$ sudo apt-get install cmake lua5.3 liblua5.3-dev libsystemd-dev lua-expat ``` To run the tests, install `lua-unit` or install it directly from here diff --git a/lsdbus-scm-0.rockspec b/lsdbus-scm-0.rockspec index c3e0b53..68d6fc9 100644 --- a/lsdbus-scm-0.rockspec +++ b/lsdbus-scm-0.rockspec @@ -16,6 +16,7 @@ source = { dependencies = { "lua >= 5.1", + "luaexpat >= 1.3.0", "compat53 >= 0.5", -- only for lua < 5.3 } diff --git a/src/introspect.c b/src/introspect.c deleted file mode 100644 index 6c09d9e..0000000 --- a/src/introspect.c +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include -#include -#include - -#include "lsdbus.h" - - -#include - -/* - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* - * convert the given D-Bus XML node to it's corresponding Lua - * representation. - */ -static int dbus_xml2lua(lua_State *L, mxml_node_t *root) -{ - mxml_node_t *node, *subnode, *intf, *prop, *met, *sig, *arg; - - node = mxmlFindElement(root, root, "node", NULL, NULL, MXML_DESCEND); - - if (!node) { - mxmlDelete(root); - luaL_error(L, "failed to find element"); - } - - lua_newtable(L); /* result */ - lua_pushstring(L, "interfaces"); - lua_newtable(L); /* interfaces */ - - for(intf = mxmlFindElement(node, node, "interface", NULL, NULL, MXML_DESCEND); - intf != NULL; - intf = mxmlFindElement(intf, node, "interface", NULL, NULL, MXML_NO_DESCEND)) { - - /* interface */ - lua_newtable(L); - - lua_pushstring(L, "name"); - lua_pushstring(L, mxmlElementGetAttr(intf, "name")); - lua_rawset(L, -3); - - /* methods */ - lua_pushstring(L, "methods"); - lua_newtable(L); - - for(met = mxmlFindElement(intf, intf, "method", NULL, NULL, MXML_DESCEND); - met != NULL; - met = mxmlFindElement(met, intf, "method", NULL, NULL, MXML_NO_DESCEND)) { - /* method */ - lua_pushstring(L, mxmlElementGetAttr(met, "name")); - lua_newtable(L); - - for(arg = mxmlFindElement(met, met, "arg", NULL, NULL, MXML_DESCEND); - arg != NULL; - arg = mxmlFindElement(arg, met, "arg", NULL, NULL, MXML_NO_DESCEND)) { - lua_newtable(L); /* arg */ - - lua_pushstring(L, "name"); - lua_pushstring(L, mxmlElementGetAttr(arg, "name")); - lua_rawset(L, -3); - - lua_pushstring(L, "type"); - lua_pushstring(L, mxmlElementGetAttr(arg, "type")); - lua_rawset(L, -3); - - lua_pushstring(L, "direction"); - lua_pushstring(L, mxmlElementGetAttr(arg, "direction")); - lua_rawset(L, -3); - - /* method[#method+1] = arg */ - lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); - } - - lua_rawset(L, -3); /* methods[name] = method */ - } - lua_rawset(L, -3); /* interface.methods = methods */ - - /* properties */ - lua_pushstring(L, "properties"); - lua_newtable(L); - - for(prop = mxmlFindElement(intf, intf, "property", NULL, NULL, MXML_DESCEND); - prop != NULL; - prop = mxmlFindElement(prop, intf, "property", NULL, NULL, MXML_NO_DESCEND)) { - lua_pushstring(L, mxmlElementGetAttr(prop, "name")); - lua_newtable(L); - - lua_pushstring(L, "type"); - lua_pushstring(L, mxmlElementGetAttr(prop, "type")); - lua_rawset(L, -3); - - lua_pushstring(L, "access"); - lua_pushstring(L, mxmlElementGetAttr(prop, "access")); - lua_rawset(L, -3); - - lua_rawset(L, -3); /* properties[name] = property */ - } - - lua_rawset(L, -3); /* interface.properties = properties */ - - /* signal */ - lua_pushstring(L, "signals"); - lua_newtable(L); - - for(sig = mxmlFindElement(intf, intf, "signal", NULL, NULL, MXML_DESCEND); - sig != NULL; - sig = mxmlFindElement(sig, intf, "signal", NULL, NULL, MXML_NO_DESCEND)) { - lua_pushstring(L, mxmlElementGetAttr(sig, "name")); - lua_newtable(L); - - for(arg = mxmlFindElement(sig, sig, "arg", NULL, NULL, MXML_DESCEND); - arg != NULL; - arg = mxmlFindElement(arg, sig, "arg", NULL, NULL, MXML_NO_DESCEND)) { - lua_newtable(L); /* arg */ - - lua_pushstring(L, "name"); - lua_pushstring(L, mxmlElementGetAttr(arg, "name")); - lua_rawset(L, -3); - - lua_pushstring(L, "type"); - lua_pushstring(L, mxmlElementGetAttr(arg, "type")); - lua_rawset(L, -3); - - /* signal[#signal+1] = arg */ - lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); - } - lua_rawset(L, -3); /* signals[name] = signal */ - } - - lua_rawset(L, -3); /* interface.signals = signals */ - - /* interfaces[#interfaces+1] = interface */ - lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); - } - lua_rawset(L, -3); /* result.interfaces = interfaces */ - - /* subnodes */ - lua_pushstring(L, "nodes"); - lua_newtable(L); - - for(subnode = mxmlFindElement(node, node, "node", NULL, NULL, MXML_DESCEND); - subnode != NULL; - subnode = mxmlFindElement(subnode, node, "node", NULL, NULL, MXML_NO_DESCEND)) { - dbg("%s", mxmlElementGetAttr(subnode, "name")); - lua_pushstring(L, mxmlElementGetAttr(subnode, "name")); - lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); - } - - lua_rawset(L, -3); /* result.nodes = nodes */ - - mxmlDelete(root); - return 0; -} - -int lsdbus_xml_fromfile(lua_State *L) -{ - - FILE *fp; - mxml_node_t *root; - - const char* f = luaL_checkstring(L, 1); - - fp = fopen(f, "r"); - - if (fp == NULL) - luaL_error(L, "failed to open %s", f); - - root = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK); - - fclose(fp); - - if (root == NULL) - luaL_error(L, "failed to parse file %s", f); - - dbus_xml2lua(L, root); - return 1; -} - -int lsdbus_xml_fromstr(lua_State *L) -{ - mxml_node_t *root; - const char* s = luaL_checkstring(L, 1); - - root = mxmlLoadString(NULL, s, MXML_OPAQUE_CALLBACK); - - if (root == NULL) - luaL_error(L, "failed to parse XML string"); - - dbus_xml2lua(L, root); - return 1; -} diff --git a/src/lsdbus.c b/src/lsdbus.c index 1853eda..f8ea920 100644 --- a/src/lsdbus.c +++ b/src/lsdbus.c @@ -564,8 +564,6 @@ static int lsdbus_bus_gc(lua_State *L) static const luaL_Reg lsdbus_f [] = { { "open", lsdbus_open }, - { "xml_fromfile", lsdbus_xml_fromfile }, - { "xml_fromstr", lsdbus_xml_fromstr }, /* { "testmsg_tolua", lsdbus_testmsg_tolua }, */ { NULL, NULL }, }; diff --git a/src/lsdbus.h b/src/lsdbus.h index 686984b..c30349d 100644 --- a/src/lsdbus.h +++ b/src/lsdbus.h @@ -91,9 +91,6 @@ struct lsdbus_slot* __lsdbus_slot_push(lua_State *L, sd_bus_slot *slot, uint32_t int lsdbus_slot_push(lua_State *L, sd_bus_slot *slot, uint32_t flags); void init_reg_vtab_user(lua_State *L); -int lsdbus_xml_fromfile(lua_State *L); -int lsdbus_xml_fromstr(lua_State *L); - void regtab_store(lua_State *L, const char* regtab, void *k, int funidx); int regtab_get(lua_State *L, const char* regtab, void *k); void regtab_clear(lua_State *L, const char* regtab, void *k); diff --git a/src/lsdbus/init.lua b/src/lsdbus/init.lua index ffb1d56..da53c6f 100644 --- a/src/lsdbus/init.lua +++ b/src/lsdbus/init.lua @@ -10,12 +10,124 @@ lsdbus.proxy = require("lsdbus.proxy") lsdbus.server = require("lsdbus.server") lsdbus.error = require("lsdbus.error") +local lom = require("lxp.lom") + lsdbus.PropIntf = 'org.freedesktop.DBus.Properties' local fmt = string.format --- Miscellaneous helpers +--[[ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]] + +local function lom2node(doc) + local interfaces = {} + local nodes = {} + for _, elt1 in ipairs(doc) do + if type(elt1) == 'table' then + if elt1.tag == 'interface' then + local methods = {} + local properties = {} + local signals = {} + for _, elt2 in ipairs(elt1) do + if type(elt2) == 'table' then + if elt2.tag == 'method' then + local args = {} + for _, elt3 in ipairs(elt2) do + if type(elt3) == 'table' and elt3.tag == 'arg' then + args[#args+1] = { + name = elt3.attr.name, + type = elt3.attr.type, + direction = elt3.attr.direction, + } + end + end + methods[elt2.attr.name] = args + elseif elt2.tag == 'property' then + properties[elt2.attr.name] = { + access = elt2.attr.access, + type = elt2.attr.type, + } + elseif elt2.tag == 'signal' then + local args = {} + for _, elt3 in ipairs(elt2) do + if type(elt3) == 'table' and elt3.tag == 'arg' then + args[#args+1] = { + name = elt3.attr.name, + type = elt3.attr.type, + } + end + end + signals[elt2.attr.name] = args + end + end + end + interfaces[#interfaces+1] = { + name = elt1.attr.name, + methods = methods, + properties = properties, + signals = signals, + } + elseif elt1.tag == 'node' then + nodes[#nodes+1] = elt1.attr.name + end + end + end + return { + name = doc.attr.name, + interfaces = interfaces, + nodes = nodes, + } +end + +function lsdbus.xml_fromfile(filename) + local f = assert(io.open(filename, 'r')) + local doc = assert(lom.parse(f)) + f:close() + return lom2node(doc) +end + +function lsdbus.xml_fromstr(str) + local doc = assert(lom.parse(str)) + return lom2node(doc) +end + --- Find the given interface in a node table -- return the interface if found function lsdbus.find_intf(node, interface) diff --git a/test/introspect.lua b/test/introspect.lua index 5e2db57..9fa3bef 100644 --- a/test/introspect.lua +++ b/test/introspect.lua @@ -4,6 +4,7 @@ local lsdb = require("lsdbus") local TestIntrospect = {} local testnode = { + name="/com/example/sample_object0", interfaces = { { name="com.example.SampleInterface0",