Add pkgmgr_installer_send_app_uninstall_signal_for_uid()
[platform/core/appfw/slp-pkgmgr.git] / installer / pkgmgr_installer.c
index 12273d1..aeb07cf 100644 (file)
  *
  */
 
-
-
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 #include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
+#include <glib.h>
 #include <gio/gio.h>
+#include <tzplatform_config.h>
 
 #include "pkgmgr_installer.h"
 #include "pkgmgr_installer_config.h"
 #include "pkgmgr_installer_debug.h"
 #include "pkgmgr_installer_info.h"
 
-#include "../client/include/comm_config.h"
-
 #include <pkgmgr-info.h>
 
 /* API export macro */
 #define CHK_PI_RET(r) \
        do { if (NULL == pi) return (r); } while (0)
 
+#define OPTVAL_PRELOAD 1000
+#define OPTVAL_FORCE_REMOVAL 1001
+
+/* Supported options */
+const char *short_opts = "k:l:i:d:c:m:t:o:r:p:s:b:e:M:y:u:w:D:A:q";
+const struct option long_opts[] = {
+       { "session-id", 1, NULL, 'k' },
+       { "license-path", 1, NULL, 'l' },
+       { "install", 1, NULL, 'i' },
+       { "uninstall", 1, NULL, 'd' },
+       { "clear", 1, NULL, 'c' },
+       { "move", 1, NULL, 'm' },
+       { "move-type", 1, NULL, 't' },
+       { "optional-data", 0, NULL, 'o' },
+       { "reinstall", 0, NULL, 'r' },
+       { "caller-pkgid", 1, NULL, 'p' },
+       { "tep-path", 1, NULL, 'e' },
+       { "tep-move", 1, NULL, 'M' },
+       { "smack", 1, NULL, 's' },
+       { "direct-manifest-install", 1, NULL, 'y' },
+       { "mount-install", 1, NULL, 'w' },
+       { "recovery", 1, NULL, 'b' },
+       { "preload", 0, NULL, OPTVAL_PRELOAD },
+       { "force-remove", 0, NULL, OPTVAL_FORCE_REMOVAL },
+       { 0, 0, 0, 0 }  /* sentinel */
+};
+
 struct pkgmgr_installer {
        int request_type;
        int move_type;
@@ -71,46 +101,49 @@ static uid_t g_target_uid;
 static const char *__get_signal_name(pkgmgr_installer *pi, const char *key)
 {
        if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0)
-               return COMM_STATUS_BROADCAST_EVENT_INSTALL_PROGRESS;
+               return key;
        else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
-               return COMM_STATUS_BROADCAST_EVENT_GET_SIZE;
+               return key;
        else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
-               return COMM_STATUS_BROADCAST_EVENT_UNINSTALL;
+               return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
 
        switch (pi->request_type) {
        case PKGMGR_REQ_INSTALL:
        case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
        case PKGMGR_REQ_MOUNT_INSTALL:
-               return COMM_STATUS_BROADCAST_EVENT_INSTALL;
+       case PKGMGR_REQ_ENABLE_PKG:
+               return PKGMGR_INSTALLER_INSTALL_EVENT_STR;
        case PKGMGR_REQ_UNINSTALL:
-               return COMM_STATUS_BROADCAST_EVENT_UNINSTALL;
+       case PKGMGR_REQ_DISABLE_PKG:
+               return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
        case PKGMGR_REQ_UPGRADE:
-               return COMM_STATUS_BROADCAST_EVENT_UPGRADE;
+               return PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
        case PKGMGR_REQ_MOVE:
-               return COMM_STATUS_BROADCAST_EVENT_MOVE;
+               return PKGMGR_INSTALLER_MOVE_EVENT_STR;
        case PKGMGR_REQ_ENABLE_APP:
-               return COMM_STATUS_BROADCAST_EVENT_ENABLE_APP;
+               return PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR;
        case PKGMGR_REQ_DISABLE_APP:
-               return COMM_STATUS_BROADCAST_EVENT_DISABLE_APP;
+               return PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR;
        case PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN:
-               return COMM_STATUS_BROADCAST_EVENT_ENABLE_APP_SPLASH_SCREEN;
+               return PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR;
        case PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN:
-               return COMM_STATUS_BROADCAST_EVENT_DISABLE_APP_SPLASH_SCREEN;
+               return PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
        }
 
-       ERR("cannot find type, send signal with type SIGNAL_STATUS");
+       ERR("cannot find type");
 
-       return COMM_STATUS_BROADCAST_SIGNAL_STATUS;
+       return NULL;
 }
 
-static int __send_signal_for_app_event(pkgmgr_installer *pi, const char *pkg_type,
-               const char *pkgid, const char *appid, const char *key, const char *val)
+static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type,
+               const char *pkgid, const char *appid, const char *key,
+               const char *val)
 {
        char *sid;
        const char *name;
        GError *err = NULL;
 
-       if (!pi || pi->conn == NULL || appid == NULL)
+       if (!pi || pi->conn == NULL)
                return -1;
 
        sid = pi->session_id;
@@ -124,10 +157,11 @@ static int __send_signal_for_app_event(pkgmgr_installer *pi, const char *pkg_typ
        }
 
        if (g_dbus_connection_emit_signal(pi->conn, NULL,
-                               COMM_STATUS_BROADCAST_OBJECT_PATH,
-                               COMM_STATUS_BROADCAST_INTERFACE, name,
+                               PKGMGR_INSTALLER_DBUS_OBJECT_PATH,
+                               PKGMGR_INSTALLER_DBUS_INTERFACE, name,
                                g_variant_new("(ussssss)", pi->target_uid, sid,
-                                       pkg_type, pkgid, appid, key, val), &err)
+                                       pkg_type, pkgid, appid ? appid : "",
+                                       key, val), &err)
                        != TRUE) {
                ERR("failed to send dbus signal: %s", err->message);
                g_error_free(err);
@@ -137,12 +171,53 @@ static int __send_signal_for_app_event(pkgmgr_installer *pi, const char *pkg_typ
        return 0;
 }
 
-static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type,
-               const char *pkgid, const char *key, const char *val)
+static int __send_signal_to_agent(uid_t uid, void *data, size_t len)
+{
+       int fd;
+       struct sockaddr_un sa;
+       int r;
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
+       if (fd == -1) {
+               ERR("failed to create socket: %d", errno);
+               return -1;
+       }
+
+       sa.sun_family = AF_UNIX;
+       snprintf(sa.sun_path, sizeof(sa.sun_path), "/run/pkgmgr/agent/%d", uid);
+
+       r = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
+       if (r == -1) {
+               ERR("failed to connect socket(%s): %d", sa.sun_path, errno);
+               close(fd);
+               return -1;
+       }
+
+       r = send(fd, data, len, 0);
+       if (r < 0) {
+               ERR("failed to send data: %d", errno);
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+
+       return 0;
+}
+
+static int __send_signal_for_event_for_uid(pkgmgr_installer *pi, uid_t uid,
+               const char *pkg_type, const char *pkgid, const char *appid,
+               const char *key, const char *val)
 {
        char *sid;
        const char *name;
-       GError *err = NULL;
+       size_t name_size;
+       GVariant *gv;
+       gsize gv_len;
+       gpointer gv_data;
+       void *data;
+       void *ptr;
+       size_t data_len;
 
        if (!pi || pi->conn == NULL)
                return -1;
@@ -151,23 +226,48 @@ static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type,
        if (!sid)
                sid = "";
 
+       data_len = sizeof(size_t) + sizeof(gsize);
+
        name = __get_signal_name(pi, key);
        if (name == NULL) {
                ERR("unknown signal type");
                return -1;
        }
-
-       if (g_dbus_connection_emit_signal(pi->conn, NULL,
-                               COMM_STATUS_BROADCAST_OBJECT_PATH,
-                               COMM_STATUS_BROADCAST_INTERFACE, name,
-                               g_variant_new("(ussssss)", pi->target_uid, sid,
-                                       pkg_type, pkgid, "", key, val), &err)
-                       != TRUE) {
-               ERR("failed to send dbus signal: %s", err->message);
-               g_error_free(err);
+       /* including null byte */
+       name_size = strlen(name) + 1;
+       data_len += name_size;
+
+       gv = g_variant_new("(ussssss)", pi->target_uid, sid,
+                       pkg_type, pkgid, appid ? appid : "", key, val);
+       if (gv == NULL) {
+               ERR("failed to create GVariant instance");
+               return -1;
+       }
+       gv_len = g_variant_get_size(gv);
+       gv_data = g_malloc(gv_len);
+       g_variant_store(gv, gv_data);
+       g_variant_unref(gv);
+       data_len += gv_len;
+
+       data = malloc(data_len);
+       ptr = data;
+       memcpy(ptr, &name_size, sizeof(size_t));
+       ptr += sizeof(size_t);
+       memcpy(ptr, &gv_len, sizeof(gsize));
+       ptr += sizeof(gsize);
+       memcpy(ptr, name, name_size);
+       ptr += name_size;
+       memcpy(ptr, gv_data, gv_len);
+
+       if (__send_signal_to_agent(uid, data, data_len)) {
+               ERR("failed to send signal to agent");
+               g_free(data);
                return -1;
        }
 
+       g_free(gv_data);
+       free(data);
+
        return 0;
 }
 
@@ -425,6 +525,11 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                        pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
                        break;
 
+               case 'u': /* uid */
+                       g_target_uid = (uid_t)atoi(optarg);
+                       pi->target_uid = (uid_t)atoi(optarg);
+                       break;
+
                        /* Otherwise */
                case '?':       /* Not an option */
                        break;
@@ -435,6 +540,11 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                }
        }
 
+       /* if target user is not set, set as tizenglobalapp user */
+       if (pi->target_uid == 0) {
+               pi->target_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+               g_target_uid = pi->target_uid;
+       }
  RET:
        return r;
 }
@@ -445,6 +555,12 @@ API int pkgmgr_installer_get_request_type(pkgmgr_installer *pi)
        return pi->request_type;
 }
 
+API uid_t pkgmgr_installer_get_uid(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->target_uid;
+}
+
 API const char *pkgmgr_installer_get_request_info(pkgmgr_installer *pi)
 {
        CHK_PI_RET(PKGMGR_REQ_INVALID);
@@ -516,7 +632,17 @@ API int pkgmgr_installer_send_app_uninstall_signal(pkgmgr_installer *pi,
                             const char *val)
 {
        int ret = 0;
-       ret = __send_signal_for_event(pi, pkg_type, pkgid,
+       ret = __send_signal_for_event(pi, pkg_type, pkgid, NULL,
+                       PKGMGR_INSTALLER_APPID_KEY_STR, val);
+       return ret;
+}
+
+API int pkgmgr_installer_send_app_uninstall_signal_for_uid(
+               pkgmgr_installer *pi, uid_t uid, const char *pkg_type,
+               const char *pkgid, const char *val)
+{
+       int ret = 0;
+       ret = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, NULL,
                        PKGMGR_INSTALLER_APPID_KEY_STR, val);
        return ret;
 }
@@ -546,7 +672,7 @@ pkgmgr_installer_send_app_signal(pkgmgr_installer *pi,
                return -1;
        }
 
-       r = __send_signal_for_app_event(pi, pkg_type, pkgid, appid, key, val);
+       r = __send_signal_for_event(pi, pkg_type, pkgid, appid, key, val);
 
        return r;
 }
@@ -568,7 +694,45 @@ pkgmgr_installer_send_signal(pkgmgr_installer *pi,
                        strcmp(val, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
                pi->request_type = PKGMGR_REQ_UPGRADE;
 
-       r = __send_signal_for_event(pi, pkg_type, pkgid, key, val);
+       r = __send_signal_for_event(pi, pkg_type, pkgid, NULL, key, val);
+
+       return r;
+}
+
+API int pkgmgr_installer_send_app_signal_for_uid(pkgmgr_installer *pi,
+               uid_t uid, const char *pkg_type, const char *pkgid,
+               const char *appid, const char *key, const char *val)
+{
+       int r = 0;
+
+       if (!pi->conn) {
+               ERR("connection is NULL");
+               return -1;
+       }
+
+       r = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, appid,
+                       key, val);
+
+       return r;
+}
+
+API int pkgmgr_installer_send_signal_for_uid(pkgmgr_installer *pi,
+               uid_t uid, const char *pkg_type, const char *pkgid,
+               const char *key, const char *val)
+{
+       int r = 0;
+
+       if (!pi->conn) {
+               ERR("connection is NULL");
+               return -1;
+       }
+
+       if (strcmp(key, PKGMGR_INSTALLER_START_KEY_STR) == 0 &&
+                       strcmp(val, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
+               pi->request_type = PKGMGR_REQ_UPGRADE;
+
+       r = __send_signal_for_event_for_uid(pi, uid, pkg_type, pkgid, NULL,
+                       key, val);
 
        return r;
 }