Implement pkgmgr-installer-signal-agent 75/82975/13
authorSangyoon Jang <s89.jang@samsung.com>
Mon, 8 Aug 2016 10:35:51 +0000 (19:35 +0900)
committerSangyoon Jang <s89.jang@samsung.com>
Mon, 22 Aug 2016 05:35:36 +0000 (14:35 +0900)
pkgmgr-installer-signal-agent receives signal information from backend
installer, and emits into user-session bus.
backend installer running as system user cannot use user session bus, so
this agent will cover for it.

Change-Id: I834782358cf37a151b44737a7592bf40c3fbeba1
Signed-off-by: Sangyoon Jang <s89.jang@samsung.com>
installer/CMakeLists.txt
installer/pkgmgr_installer_signal_agent.c [new file with mode: 0644]
packaging/pkgmgr-installer-signal-agent.service [new file with mode: 0644]
packaging/pkgmgr-installer-signal-agent.socket [new file with mode: 0644]
packaging/pkgmgr.conf
packaging/pkgmgr.spec

index 379aa1454c13eb4765e51462325e8c760adacd9d..48bafcef11ca37f74e6ad8f32f7804244dbc9321 100644 (file)
@@ -30,6 +30,11 @@ foreach(flag ${installer_pkgs_CFLAGS})
        set(installer_pkgs_CFLAGS_str "${installer_pkgs_CFLAGS_str} ${flag}")
 endforeach()
 
+PKG_CHECK_MODULES(AGENT_DEPS REQUIRED glib-2.0 gio-2.0 dlog libsystemd-daemon)
+FOREACH(FLAG ${AGENT_DEPS_CFLAGS})
+       SET(AGENT_CFLAGS "${AGENT_CFLAGS} ${FLAG}")
+ENDFOREACH()
+
 ### Build modules
 
 ## pkgmgr_installer object (by youmin.ha)
@@ -48,3 +53,10 @@ INSTALL(TARGETS pkgmgr_installer DESTINATION ${LIB_INSTALL_DIR} COMPONENT Runtim
 INSTALL(FILES pkgmgr_installer.h DESTINATION include/pkgmgr)
 INSTALL(FILES pkgmgr_installer_info.h DESTINATION include/pkgmgr)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-installer.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+## pkgmgr_installer_signal_agent
+ADD_EXECUTABLE(pkgmgr-installer-signal-agent pkgmgr_installer_signal_agent.c)
+SET_TARGET_PROPERTIES(pkgmgr-installer-signal-agent PROPERTIES COMPILE_FLAGS "${AGENT_CFLAGS}")
+TARGET_LINK_LIBRARIES(pkgmgr-installer-signal-agent ${AGENT_DEPS_LDFLAGS})
+
+INSTALL(TARGETS pkgmgr-installer-signal-agent DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
diff --git a/installer/pkgmgr_installer_signal_agent.c b/installer/pkgmgr_installer_signal_agent.c
new file mode 100644 (file)
index 0000000..e96f963
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <linux/limits.h>
+
+#include <glib.h>
+#include <glib-unix.h>
+#include <gio/gio.h>
+#include <systemd/sd-daemon.h>
+
+#include <dlog.h>
+
+#include "../client/include/comm_config.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "PKGMGR_INSTALLER_SIGNAL_AGENT"
+
+#define BUFMAX 4096
+
+static int server_fd;
+static GMainLoop *loop;
+static guint sid;
+static guint tid;
+static GDBusConnection *conn;
+
+static int __create_server_socket(const char *path)
+{
+       int r;
+       int fd;
+       struct sockaddr_un sa;
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1) {
+               LOGE("socket create failed: %d", errno);
+               return -1;
+       }
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sun_family = AF_UNIX;
+       snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", path);
+
+       r = unlink(sa.sun_path);
+       if (r == -1 && errno != ENOENT) {
+               LOGE("unlink(%s) failed: %d", sa.sun_path, errno);
+               close(fd);
+               return -1;
+       }
+
+       r = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
+       if (r == -1) {
+               LOGE("bind(%s) failed: %d", sa.sun_path, errno);
+               close(fd);
+               return -1;
+       }
+
+       r = chmod(sa.sun_path, 0666);
+       if (r == -1)
+               LOGW("chmod(%s) failed: %d", sa.sun_path, errno);
+
+       r = listen(fd, SOMAXCONN);
+       if (r == -1) {
+               LOGE("listen(%s) failed: %d", sa.sun_path, errno);
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+static int __get_server_socket(const char *path)
+{
+       int i;
+       int n;
+       int r;
+       int fd = -1;
+
+       n = sd_listen_fds(0);
+       if (n < 0) {
+               LOGE("sd_listen_fds: %d", n);
+               return -1;
+       } else if (n == 0) {
+               return __create_server_socket(path);
+       }
+
+       for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + n; i++) {
+               r = sd_is_socket_unix(i, SOCK_STREAM, -1, path, 0);
+               if (r > 0) {
+                       fd = i;
+                       break;
+               }
+       }
+
+       if (fd == -1) {
+               LOGE("socket is not passed, create server socket");
+               return __create_server_socket(path);
+       }
+
+       return fd;
+}
+
+static void __emit_signal(const char *name, GVariant *gv)
+{
+       GError *err = NULL;
+
+       if (g_dbus_connection_emit_signal(conn, NULL,
+                               COMM_STATUS_BROADCAST_OBJECT_PATH,
+                               COMM_STATUS_BROADCAST_INTERFACE,
+                               name, gv, &err) != TRUE) {
+               LOGE("g_dbus_connection_emit_signal failed: %s", err->message);
+               g_error_free(err);
+       }
+}
+
+static gboolean __quit(gpointer user_data)
+{
+       g_main_loop_quit(loop);
+       return FALSE;
+}
+
+/**
+ * packet format:
+ * +----------------+-------------+-----------+-------------------+
+ * |signal name size|GVariant size|signal name|serialized GVariant|
+ * +----------------+-------------+-----------+-------------------+
+ */
+static gboolean __handle_signal(gint fd, GIOCondition cond, gpointer user_data)
+{
+       int r;
+       unsigned char buf[BUFMAX];
+       int clifd;
+       struct sockaddr_un sa;
+       socklen_t s = sizeof(sa);
+       size_t type_len;
+       char *type_name;
+       gsize data_len;
+       gpointer data;
+       GVariant *gv;
+
+       clifd = accept(fd, (struct sockaddr *)&sa, &s);
+       if (clifd == -1) {
+               LOGE("accept failed: %d", errno);
+               return FALSE;
+       }
+
+       r = recv(clifd, buf, sizeof(size_t) + sizeof(gsize), 0);
+       if (r < 0) {
+               LOGE("recv failed: %d", errno);
+               close(clifd);
+               return FALSE;
+       } else if (r == 0) {
+               LOGE("client fd already closed");
+               close(clifd);
+               return FALSE;
+       }
+
+       memcpy(&type_len, buf, sizeof(size_t));
+       memcpy(&data_len, buf + sizeof(int), sizeof(gsize));
+
+       r = recv(clifd, buf, type_len + data_len, 0);
+       if (r < 0) {
+               LOGE("recv failed: %d", errno);
+               close(clifd);
+               return FALSE;
+       } else if (r == 0) {
+               LOGE("client fd already closed");
+               close(clifd);
+               return FALSE;
+       }
+
+       /* get signal name (including terminating null byte) */
+       type_name = malloc(type_len);
+       memcpy(type_name, buf, type_len);
+
+       /* get data */
+       data = malloc(data_len);
+       memcpy(data, buf + type_len, data_len);
+
+       gv = g_variant_new_from_data(G_VARIANT_TYPE("(ussssss)"), data,
+                       data_len, TRUE, NULL, NULL);
+       __emit_signal(type_name, gv);
+
+       g_variant_unref(gv);
+       free(data);
+       free(type_name);
+       close(clifd);
+
+       /* renew timeout */
+       g_source_remove(tid);
+       tid = g_timeout_add_seconds(10, __quit, NULL);
+
+       return TRUE;
+}
+
+static int __init(void)
+{
+       char path[PATH_MAX];
+       GError *err = NULL;
+
+       snprintf(path, sizeof(path), "/run/pkgmgr/agent/%d", getuid());
+       server_fd = __get_server_socket(path);
+       if (server_fd < 0) {
+               LOGE("server init failed");
+               return -1;
+       }
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
+       if (conn == NULL) {
+               LOGE("g_bus_get_sync failed: %s", err->message);
+               g_error_free(err);
+               close(server_fd);
+               return -1;
+       }
+
+       loop = g_main_loop_new(NULL, FALSE);
+       sid = g_unix_fd_add(server_fd, G_IO_IN, __handle_signal, NULL);
+       tid = g_timeout_add_seconds(10, __quit, NULL);
+
+       return 0;
+}
+
+static void __fini(void)
+{
+       g_source_remove(sid);
+       g_main_loop_unref(loop);
+       g_object_unref(conn);
+       close(server_fd);
+}
+
+int main(int argc, char *argv[])
+{
+       int r;
+
+       r = __init();
+       if (r < 0)
+               return -1;
+
+       g_main_loop_run(loop);
+
+       __fini();
+
+       return 0;
+}
diff --git a/packaging/pkgmgr-installer-signal-agent.service b/packaging/pkgmgr-installer-signal-agent.service
new file mode 100644 (file)
index 0000000..545ff4a
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Package Manager Installer Signal Agent on User Session
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/pkgmgr-installer-signal-agent
diff --git a/packaging/pkgmgr-installer-signal-agent.socket b/packaging/pkgmgr-installer-signal-agent.socket
new file mode 100644 (file)
index 0000000..92caf14
--- /dev/null
@@ -0,0 +1,7 @@
+[Socket]
+ListenStream=/run/pkgmgr/agent/%U
+DirectoryMode=0777
+ExecStartPost=/usr/bin/chmod 0777 /run/pkgmgr/agent/%U
+
+[Install]
+WantedBy=sockets.target
index 129544b1ccbb4bef17bfa5b18b2ace544d7ddf75..c92c82365fad7e062c99df489cee677f15272231 100644 (file)
@@ -1,3 +1,4 @@
 d      /tmp/pkgmgr     1777    root    users
 t      /tmp/pkgmgr     -       -       -       -       security.SMACK64="User::App::Shared"
 t      /tmp/pkgmgr     -       -       -       -       security.SMACK64TRANSMUTE="TRUE"
+d      /run/pkgmgr/agent       0777    root    users   -
index 3dfcbb7e84c370bdf914f1c15aef93ec38ae65e4..326702dc548762c6fcf9f0472b22e73f5f09f849 100644 (file)
@@ -14,6 +14,8 @@ Source1004: %{name}-installer.manifest
 Source1005: %{name}-installer-devel.manifest
 Source1006: %{name}-types-devel.manifest
 Source1007: %{name}.conf
+Source1008: %{name}-installer-signal-agent.service
+Source1009: %{name}-installer-signal-agent.socket
 Requires(post): /usr/sbin/useradd
 
 BuildRequires:  cmake
@@ -31,6 +33,7 @@ BuildRequires:  pkgconfig(security-manager)
 BuildRequires:  pkgconfig(xdgmime)
 BuildRequires:  pkgconfig(db-util)
 BuildRequires:  pkgconfig(libsmack)
+BuildRequires:  pkgconfig(libsystemd-daemon)
 BuildRequires:  pkgmgr-info-parser-devel
 BuildRequires:  pkgmgr-info-parser
 BuildRequires:  fdupes
@@ -99,6 +102,11 @@ rm -f %{buildroot}%{_libdir}/libpkgmgr_parser_lib_sample.so
 mkdir -p %{buildroot}%{_tmpfilesdir}/
 install -m 0644 %{SOURCE1007} %{buildroot}%{_tmpfilesdir}/pkgmgr.conf
 
+mkdir -p %{buildroot}%{_unitdir_user}/sockets.target.wants
+install -m 0644 %{SOURCE1008} %{buildroot}%{_unitdir_user}/pkgmgr-installer-signal-agent.service
+install -m 0644 %{SOURCE1009} %{buildroot}%{_unitdir_user}/pkgmgr-installer-signal-agent.socket
+ln -sf ../alarm_session_agent.socket %{buildroot}%{_unitdir_user}/sockets.target.wants/pkgmgr-installer-signal-agent.socket
+
 mkdir -p %{buildroot}%{_sysconfdir}/package-manager/backend
 mkdir -p %{buildroot}%{_sysconfdir}/package-manager/backendlib
 mkdir -p %{buildroot}%{_sysconfdir}/opt/upgrade
@@ -160,6 +168,10 @@ HOME="$saveHOME"
 %manifest %{name}-installer.manifest
 %defattr(-,root,root,-)
 %{_libdir}/libpkgmgr_installer.so.*
+%{_bindir}/pkgmgr-installer-signal-agent
+%{_unitdir_user}/pkgmgr-installer-signal-agent.service
+%{_unitdir_user}/pkgmgr-installer-signal-agent.socket
+%{_unitdir_user}/sockets.target.wants/pkgmgr-installer-signal-agent.socket
 
 %files installer-devel
 %manifest %{name}-installer-devel.manifest