diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | hw/systemd.c | 177 | ||||
-rw-r--r-- | hw/systemd.h | 37 | ||||
-rwxr-xr-x | packaging/libdevice-node.spec | 1 |
4 files changed, 217 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c4e82d..bdba1d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/${INC_DIR}) INCLUDE(FindPkgConfig) -pkg_check_modules(rpkgs REQUIRED dlog vconf glib-2.0) +pkg_check_modules(rpkgs REQUIRED dlog vconf glib-2.0 libsystemd) FOREACH(flag ${rpkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${rpkgs_LDFLAGS} "-ldl") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION}) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -ADD_LIBRARY(hwcommon SHARED hw/common.c) +ADD_LIBRARY(hwcommon SHARED hw/common.c hw/systemd.c) TARGET_LINK_LIBRARIES(hwcommon ${rpkgs_LDFLAGS} "-ldl") SET_TARGET_PROPERTIES(hwcommon PROPERTIES SOVERSION ${VERSION}) INSTALL(TARGETS hwcommon DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/hw/systemd.c b/hw/systemd.c new file mode 100644 index 0000000..97d32ce --- /dev/null +++ b/hw/systemd.c @@ -0,0 +1,177 @@ +/* + * libdevice-node + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdbool.h> +#include <hw/systemd.h> +#include <systemd/sd-bus.h> + +#define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1" +#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" +#define SYSTEMD_DBUS_MANAGER_IFACE "org.freedesktop.systemd1.Manager" + +#define SYSTEMD_SOCKET_SUFFIX ".socket" +#define MAX_SOCKET_NAME 1024 + +#define SYSTEMD_SERVICE_SUFFIX ".service" +#define MAX_SERVICE_NAME 1024 + +#ifndef EXPORT +#define EXPORT __attribute__ ((visibility("default"))) +#endif + +struct bus_ctx { + const char *unit; + sd_event *loop; +}; + +static int socket_started(sd_bus_message *m, void *userdata, + sd_bus_error *ret_error) +{ + struct bus_ctx *ctx = userdata; + char *signal_unit; + int ret; + + ret = sd_bus_message_read(m, "uoss", NULL, NULL, &signal_unit, NULL); + if (ret < 0) { + sd_event_exit(ctx->loop, ret); + return 0; + } + + if (!strcmp(signal_unit, ctx->unit)) + sd_event_exit(ctx->loop, 0); + + return 0; +} + +static int systemd_unit_interface_sync(const char *method, const char *unit, + bool wait) +{ + sd_bus *bus = NULL; + sd_event *loop = NULL; + struct bus_ctx ctx; + int ret; + + ret = sd_bus_open_system(&bus); + if (ret < 0) + return ret; + + if (wait) { + ret = sd_event_new(&loop); + if (ret < 0) + goto unref_bus; + + ctx.loop = loop; + ctx.unit = unit; + + ret = sd_bus_attach_event(bus, loop, SD_EVENT_PRIORITY_NORMAL); + if (ret < 0) + goto unref_loop; + + ret = sd_bus_add_match(bus, NULL, + "type='signal'," + "sender='" SYSTEMD_DBUS_SERVICE "'," + "interface='" SYSTEMD_DBUS_MANAGER_IFACE "'," + "member='JobRemoved'," + "path_namespace='" SYSTEMD_DBUS_PATH "'", + socket_started, + &ctx); + if (ret < 0) + goto unref_loop; + } + + + ret = sd_bus_call_method(bus, + SYSTEMD_DBUS_SERVICE, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_MANAGER_IFACE, + method, + NULL, + NULL, + "ss", + unit, + "replace"); + if (ret < 0) + goto unref_loop; + + if (wait) + ret = sd_event_loop(loop); + +unref_loop: + if (wait) + sd_event_unref(loop); +unref_bus: + sd_bus_unref(bus); + return ret; +} + +EXPORT int systemd_start_service(const char *service_name) +{ + char unit[MAX_SERVICE_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SERVICE_SUFFIX, + service_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StartUnit", unit, true); +} + +EXPORT int systemd_stop_service(const char *service_name) +{ + char unit[MAX_SERVICE_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SERVICE_SUFFIX, + service_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StopUnit", unit, false); +} + +EXPORT int systemd_start_socket(const char *socket_name) +{ + char unit[MAX_SOCKET_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SOCKET_SUFFIX, + socket_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + + return systemd_unit_interface_sync("StartUnit", unit, true); +} + +EXPORT int systemd_stop_socket(const char *socket_name) +{ + char unit[MAX_SOCKET_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SOCKET_SUFFIX, + socket_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StopUnit", unit, false); +} diff --git a/hw/systemd.h b/hw/systemd.h new file mode 100644 index 0000000..28ce944 --- /dev/null +++ b/hw/systemd.h @@ -0,0 +1,37 @@ +/* + * libdevice-node + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __HW_SYSTEMD_H__ +#define __HW_SYSTEMD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int systemd_start_service(const char *service_name); +int systemd_stop_service(const char *service_name); +int systemd_start_socket(const char *socket_name); +int systemd_stop_socket(const char *socket_name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __HW_SYSTEMD_H__ */ + diff --git a/packaging/libdevice-node.spec b/packaging/libdevice-node.spec index 0aef2a2..bdfd0de 100755 --- a/packaging/libdevice-node.spec +++ b/packaging/libdevice-node.spec @@ -13,6 +13,7 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(gmock) BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(libsystemd) %description development package of library to control OAL APIs |