Add new pkgmar_installer_info API
[platform/core/appfw/slp-pkgmgr.git] / installer / pkgmgr_installer.c
index c076713..e9a0aa7 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 "../client/include/comm_config.h"
+#include "pkgmgr_installer_info.h"
 
 #include <pkgmgr-info.h>
 
 #define CHK_PI_RET(r) \
        do { if (NULL == pi) return (r); } while (0)
 
+#define OPTVAL_PRELOAD 1000
+#define OPTVAL_FORCE_REMOVAL 1001
+#define OPTVAL_PRELOAD_RW 1002
+#define OPTVAL_NO_REMOVAL 1003
+#define OPTVAL_KEEP_RWDATA 1004
+#define OPTVAL_PARTIAL_RW 1005
+#define OPTVAL_MIGRATE_EXTIMG 1006
+
+/* 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:qG";
+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' },
+       { "debug-mode", 0, NULL, 'G' },
+       { "preload", 0, NULL, OPTVAL_PRELOAD }, /* for preload RO */
+       { "force-remove", 0, NULL, OPTVAL_FORCE_REMOVAL }, /* for preload RO/RW */
+       { "preload-rw", 0, NULL, OPTVAL_PRELOAD_RW }, /* for preload RW */
+       { "no-remove", 0, NULL, OPTVAL_NO_REMOVAL }, /* for preload RW */
+       { "keep-rwdata", 0, NULL, OPTVAL_KEEP_RWDATA }, /* for preload RW */
+       { "partial-rw", 0, NULL, OPTVAL_PARTIAL_RW }, /* for preload RO */
+       { "migrate-extimg", 1, NULL, OPTVAL_MIGRATE_EXTIMG },
+       { 0, 0, 0, 0 }  /* sentinel */
+};
+
 struct pkgmgr_installer {
        int request_type;
        int move_type;
@@ -62,67 +104,90 @@ struct pkgmgr_installer {
        int is_tep_included;
        int is_preload;
        int force_removal;
+       int is_preload_rw;
+       int no_removal;
+       int keep_rwdata;
+       int partial_rw;
+       int debug_mode;
        GDBusConnection *conn;
 };
 
-static const char *__get_signal_name(pkgmgr_installer *pi, const char *key)
+static uid_t g_target_uid;
+static pkgmgr_privilege_level g_privilege_level = PM_PRIVILEGE_UNKNOWN;
+
+static const char *__get_signal_name(pkgmgr_installer *pi, const char *key,
+               const char *pkg_type)
 {
        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;
+       else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0)
+               return pkg_type;
 
        switch (pi->request_type) {
        case PKGMGR_REQ_INSTALL:
-               return COMM_STATUS_BROADCAST_EVENT_INSTALL;
+       case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
+       case PKGMGR_REQ_MOUNT_INSTALL:
+       case PKGMGR_REQ_REINSTALL:
+       case PKGMGR_REQ_ENABLE_PKG:
+       case PKGMGR_REQ_RECOVER:
+               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;
+       case PKGMGR_REQ_CLEAR:
+               return PKGMGR_INSTALLER_CLEAR_EVENT_STR;
+       case PKGMGR_REQ_GETSIZE:
+               return PKGMGR_INSTALLER_GET_SIZE_KEY_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;
        if (!sid)
                sid = "";
 
-       name = __get_signal_name(pi, key);
+       name = __get_signal_name(pi, key, pkg_type);
        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,
+                               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);
@@ -132,12 +197,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, MSG_NOSIGNAL);
+       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;
@@ -146,23 +252,48 @@ static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type,
        if (!sid)
                sid = "";
 
-       name = __get_signal_name(pi, key);
+       data_len = sizeof(size_t) + sizeof(gsize);
+
+       name = __get_signal_name(pi, key, pkg_type);
        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);
+       g_free(gv_data);
+
+       if (__send_signal_to_agent(uid, data, data_len)) {
+               ERR("failed to send signal to agent");
+               free(data);
                return -1;
        }
 
+       free(data);
+
        return 0;
 }
 
@@ -246,6 +377,7 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
        int mode = 0;
 
        pi->target_uid = getuid();
+       g_target_uid = pi->target_uid;
        while (1) {
                c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx);
                /* printf("c=%d %c\n", c, c); //debug */
@@ -254,11 +386,40 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                switch (c) {
                case OPTVAL_PRELOAD:    /* request for preload app */
                        pi->is_preload = 1;
-                       DBG("preload request [%d]", pi->is_preload );
+                       DBG("preload request [%d]", pi->is_preload);
                        break;
                case OPTVAL_FORCE_REMOVAL:      /* request for force-remove */
                        pi->force_removal = 1;
-                       DBG("force-remove request [%d]", pi->force_removal );
+                       DBG("force-remove request [%d]", pi->force_removal);
+                       break;
+               case OPTVAL_PRELOAD_RW: /* request for preload-rw app */
+                       pi->is_preload_rw = 1;
+                       DBG("preload-rw request [%d]", pi->is_preload_rw);
+                       break;
+               case OPTVAL_NO_REMOVAL: /* request for no-remove */
+                       pi->no_removal = 1;
+                       DBG("no-remove request [%d]", pi->no_removal);
+                       break;
+               case OPTVAL_KEEP_RWDATA:        /* request for keep-rwdata */
+                       pi->keep_rwdata = 1;
+                       DBG("keep-rwdata request [%d]", pi->keep_rwdata);
+                       break;
+               case OPTVAL_PARTIAL_RW: /* request for partial-rw */
+                       pi->partial_rw = 1;
+                       DBG("partial-rw request [%d]", pi->partial_rw);
+                       break;
+               case OPTVAL_MIGRATE_EXTIMG:
+                       /* request for legacy extimg migration */
+                       if (mode) {
+                               r = -EINVAL;
+                               goto RET;
+                       }
+                       mode = OPTVAL_MIGRATE_EXTIMG;
+                       pi->request_type = PKGMGR_REQ_MIGRATE_EXTIMG;
+                       if (pi->pkgmgr_info)
+                               free(pi->pkgmgr_info);
+                       pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
+                       DBG("legacy extimg migration requested");
                        break;
                case 'k':       /* session id */
                        if (pi->session_id)
@@ -282,12 +443,11 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                        if (pi->pkgmgr_info)
                                free(pi->pkgmgr_info);
                        pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
-                       DBG("option is [i] pkgid[%s]", pi->pkgmgr_info );
-                       if (pi->pkgmgr_info && strlen(pi->pkgmgr_info)==0){
+                       DBG("option is [i] pkgid[%s]", pi->pkgmgr_info);
+                       if (pi->pkgmgr_info && strlen(pi->pkgmgr_info) == 0)
                                free(pi->pkgmgr_info);
-                       }else{
+                       else
                                mode = 'i';
-                       }
                        break;
 
                case 'e':       /* install */
@@ -388,6 +548,12 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                        pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
                        break;
 
+               case 'w': /* pkgid for mount installation */
+                       mode = 'w';
+                       pi->request_type = PKGMGR_REQ_MOUNT_INSTALL;
+                       pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
+                       break;
+
                case 'b': /* recovery */
                        if (mode) {
                                r = -EINVAL;
@@ -400,6 +566,29 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi,
                        pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
                        break;
 
+               case 'D': /* disable pkg */
+                       pi->request_type = PKGMGR_REQ_DISABLE_PKG;
+                       if (pi->pkgmgr_info)
+                               free(pi->pkgmgr_info);
+                       pi->pkgmgr_info = strndup(optarg, MAX_STRLEN);
+                       break;
+
+               case 'A': /* enable pkg */
+                       pi->request_type = PKGMGR_REQ_ENABLE_PKG;
+                       if (pi->pkgmgr_info)
+                               free(pi->pkgmgr_info);
+                       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;
+
+               case 'G': /* debug mode */
+                       pi->debug_mode = 1;
+                       break;
+
                        /* Otherwise */
                case '?':       /* Not an option */
                        break;
@@ -410,6 +599,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;
 }
@@ -420,6 +614,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);
@@ -485,13 +685,53 @@ API int pkgmgr_installer_get_force_removal(pkgmgr_installer *pi)
        return pi->force_removal;
 }
 
+API int pkgmgr_installer_get_is_preload_rw(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->is_preload_rw;
+}
+
+API int pkgmgr_installer_get_no_removal(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->no_removal;
+}
+
+API int pkgmgr_installer_get_keep_rwdata(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->keep_rwdata;
+}
+
+API int pkgmgr_installer_get_partial_rw(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->partial_rw;
+}
+
+API int pkgmgr_installer_get_debug_mode(pkgmgr_installer *pi)
+{
+       CHK_PI_RET(PKGMGR_REQ_INVALID);
+       return pi->debug_mode;
+}
+
 API int pkgmgr_installer_send_app_uninstall_signal(pkgmgr_installer *pi,
                             const char *pkg_type,
                             const char *pkgid,
                             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;
 }
@@ -502,6 +742,7 @@ API int pkgmgr_installer_set_uid(pkgmgr_installer *pi, uid_t uid)
                return -1;
 
        pi->target_uid = uid;
+       g_target_uid = pi->target_uid;
 
        return 0;
 }
@@ -520,7 +761,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;
 }
@@ -538,10 +779,49 @@ pkgmgr_installer_send_signal(pkgmgr_installer *pi,
                return -1;
        }
 
-       if (strcmp(key, PKGMGR_INSTALLER_UPGRADE_EVENT_STR) == 0)
+       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(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;
 }
@@ -598,3 +878,24 @@ API int pkgmgr_installer_delete_certinfo(const char *pkgid)
        ret = pkgmgrinfo_delete_certinfo(pkgid);
        return ret;
 }
+
+API int pkgmgr_installer_set_privilege_level(pkgmgr_privilege_level level)
+{
+       g_privilege_level = level;
+
+       return 0;
+}
+
+API int pkgmgr_installer_info_get_target_uid(uid_t *uid)
+{
+       *uid = g_target_uid;
+
+       return 0;
+}
+
+API int pkgmgr_installer_info_get_privilege_level(pkgmgr_privilege_level *level)
+{
+       *level = g_privilege_level;
+
+       return 0;
+}