Fix bug on handling request args
[platform/core/appfw/pkgmgr-server.git] / src / request.c
index 3269b24..0c3d41f 100644 (file)
@@ -21,6 +21,7 @@ static const char instropection_xml[] =
        "  <interface name='org.tizen.pkgmgr'>"
        "    <method name='install'>"
        "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='s' name='pkgtype' direction='in'/>"
        "      <arg type='s' name='pkgpath' direction='in'/>"
        "      <arg type='as' name='args' direction='in'/>"
        "      <arg type='i' name='ret' direction='out'/>"
@@ -34,6 +35,7 @@ static const char instropection_xml[] =
        "    </method>"
        "    <method name='mount_install'>"
        "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='s' name='pkgtype' direction='in'/>"
        "      <arg type='s' name='pkgpath' direction='in'/>"
        "      <arg type='as' name='args' direction='in'/>"
        "      <arg type='i' name='ret' direction='out'/>"
@@ -76,6 +78,18 @@ static const char instropection_xml[] =
        "      <arg type='i' name='ret' direction='out'/>"
        "      <arg type='s' name='reqkey' direction='out'/>"
        "    </method>"
+       "    <method name='enable_apps'>"
+       "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='as' name='appids' direction='in'/>"
+       "      <arg type='i' name='ret' direction='out'/>"
+       "      <arg type='s' name='reqkey' direction='out'/>"
+       "    </method>"
+       "    <method name='disable_apps'>"
+       "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='as' name='appids' direction='in'/>"
+       "      <arg type='i' name='ret' direction='out'/>"
+       "      <arg type='s' name='reqkey' direction='out'/>"
+       "    </method>"
        "    <method name='enable_global_app_for_uid'>"
        "      <arg type='u' name='uid' direction='in'/>"
        "      <arg type='s' name='appid' direction='in'/>"
@@ -95,6 +109,13 @@ static const char instropection_xml[] =
        "      <arg type='i' name='ret' direction='out'/>"
        "      <arg type='s' name='reqkey' direction='out'/>"
        "    </method>"
+       "    <method name='getsize_sync'>"
+       "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='s' name='pkgid' direction='in'/>"
+       "      <arg type='i' name='get_type' direction='in'/>"
+       "      <arg type='i' name='ret' direction='out'/>"
+       "      <arg type='x' name='size_info' direction='out'/>"
+       "    </method>"
        "    <method name='cleardata'>"
        "      <arg type='u' name='uid' direction='in'/>"
        "      <arg type='s' name='pkgid' direction='in'/>"
@@ -160,6 +181,17 @@ static const char instropection_xml[] =
        "      <arg type='i' name='result' direction='out'/>"
        "      <arg type='i' name='ret' direction='out'/>"
        "    </method>"
+       "    <method name='set_app_label'>"
+       "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='s' name='appid' direction='in'/>"
+       "      <arg type='s' name='label' direction='in'/>"
+       "      <arg type='i' name='ret' direction='out'/>"
+       "    </method>"
+       "    <method name='migrate_external_image'>"
+       "      <arg type='u' name='uid' direction='in'/>"
+       "      <arg type='s' name='pkgid' direction='in'/>"
+       "      <arg type='i' name='ret' direction='out'/>"
+       "    </method>"
        "  </interface>"
        "</node>";
 static GDBusNodeInfo *instropection_data;
@@ -182,7 +214,7 @@ static char *__generate_reqkey(const char *pkgid)
        size = strlen(pkgid) + strlen(timestr) + 2;
        str_req_key = (char *)calloc(size, sizeof(char));
        if (str_req_key == NULL) {
-               DBG("calloc failed");
+               ERR("calloc failed");
                return NULL;
        }
        snprintf(str_req_key, size, "%s_%s", pkgid, timestr);
@@ -227,7 +259,6 @@ static int __is_admin_user(uid_t uid)
        return 1;
 }
 
-#define REGULAR_USER 5000
 static int __check_caller_permission(uid_t uid,
                GDBusMethodInvocation *invocation, GVariant *parameters)
 {
@@ -272,8 +303,9 @@ static int __handle_request_install(uid_t caller_uid,
                GDBusMethodInvocation *invocation, GVariant *parameters)
 {
        uid_t target_uid = (uid_t)-1;
+       char *arg_pkgtype = NULL;
        const char *pkgtype;
-       char *pkgpath = NULL;
+       const char *pkgpath = NULL;
        char *args = NULL;
        char *reqkey = NULL;
        gchar **tmp_args = NULL;
@@ -282,8 +314,10 @@ static int __handle_request_install(uid_t caller_uid,
        GVariant *value;
        int i = 0;
        int len = 0;
+       size_t s = 0;
 
-       g_variant_get(parameters, "(u&s@as)", &target_uid, &pkgpath, &value);
+       g_variant_get(parameters, "(u&s&s@as)", &target_uid, &arg_pkgtype,
+                       &pkgpath, &value);
        tmp_args = (gchar **)g_variant_get_strv(value, &args_count);
 
        for (i = 0; i < args_count; i++)
@@ -299,9 +333,12 @@ static int __handle_request_install(uid_t caller_uid,
        }
 
        for (i = 0; i < args_count; i++) {
-               strncat(args, tmp_args[i], strlen(tmp_args[i]));
-               if (i != args_count - 1)
-                       strncat(args, " ", strlen(" "));
+               strncat(args, tmp_args[i], len - s - 1);
+               s += strlen(tmp_args[i]);
+               if (i != args_count - 1) {
+                       strncat(args, " ", len - s - 1);
+                       s += strlen(" ");
+               }
        }
 
        if (target_uid == (uid_t)-1 || pkgpath == NULL) {
@@ -311,7 +348,10 @@ static int __handle_request_install(uid_t caller_uid,
                goto catch;
        }
 
+       pkgpath = _get_adjusted_pkgpath(pkgpath, caller_uid);
        pkgtype = _get_pkgtype_from_file(pkgpath);
+       if (!pkgtype && arg_pkgtype && strlen(arg_pkgtype))
+               pkgtype = (const char *)arg_pkgtype;
        if (pkgtype == NULL) {
                g_dbus_method_invocation_return_value(invocation,
                                g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
@@ -357,8 +397,9 @@ static int __handle_request_mount_install(uid_t caller_uid,
        GDBusMethodInvocation *invocation, GVariant *parameters)
 {
        uid_t target_uid = (uid_t)-1;
+       char *arg_pkgtype = NULL;
        const char *pkgtype;
-       char *pkgpath = NULL;
+       const char *pkgpath = NULL;
        char *args = NULL;
        char *reqkey = NULL;
        gchar **tmp_args = NULL;
@@ -367,8 +408,10 @@ static int __handle_request_mount_install(uid_t caller_uid,
        GVariant *value;
        int i = 0;
        int len = 0;
+       size_t s = 0;
 
-       g_variant_get(parameters, "(u&s@as)", &target_uid, &pkgpath, &value);
+       g_variant_get(parameters, "(u&s&s@as)", &target_uid, &arg_pkgtype,
+                       &pkgpath, &value);
        tmp_args = (gchar **)g_variant_get_strv(value, &args_count);
 
        for (i = 0; i < args_count; i++)
@@ -384,9 +427,12 @@ static int __handle_request_mount_install(uid_t caller_uid,
        }
 
        for (i = 0; i < args_count; i++) {
-               strncat(args, tmp_args[i], strlen(tmp_args[i]));
-               if (i != args_count - 1)
-                       strncat(args, " ", strlen(" "));
+               strncat(args, tmp_args[i], len - s - 1);
+               s += strlen(tmp_args[i]);
+               if (i != args_count - 1) {
+                       strncat(args, " ", len - s - 1);
+                       s += strlen(" ");
+               }
        }
 
        if (target_uid == (uid_t)-1 || pkgpath == NULL) {
@@ -396,7 +442,10 @@ static int __handle_request_mount_install(uid_t caller_uid,
                goto catch;
        }
 
+       pkgpath = _get_adjusted_pkgpath(pkgpath, caller_uid);
        pkgtype = _get_pkgtype_from_file(pkgpath);
+       if (!pkgtype && arg_pkgtype && strlen(arg_pkgtype))
+               pkgtype = (const char *)arg_pkgtype;
        if (pkgtype == NULL) {
                g_dbus_method_invocation_return_value(invocation,
                                g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
@@ -456,7 +505,7 @@ static int __handle_request_reinstall(uid_t caller_uid,
        pkgtype = _get_pkgtype_from_pkgid(pkgid, target_uid);
        if (pkgtype == NULL) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+                               g_variant_new("(is)", PKGMGR_R_ENOPKG, ""));
                return -1;
        }
 
@@ -502,7 +551,7 @@ static int __handle_request_uninstall(uid_t caller_uid,
        pkgtype = _get_pkgtype_from_pkgid(pkgid, target_uid);
        if (pkgtype == NULL) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+                               g_variant_new("(is)", PKGMGR_R_ENOPKG, ""));
                return -1;
        }
 
@@ -550,7 +599,7 @@ static int __handle_request_move(uid_t caller_uid,
        pkgtype = _get_pkgtype_from_pkgid(pkgid, target_uid);
        if (pkgtype == NULL) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+                               g_variant_new("(is)", PKGMGR_R_ENOPKG, ""));
                return -1;
        }
 
@@ -608,7 +657,7 @@ static int __handle_request_enable_pkgs(uid_t caller_uid,
                if (pkgtype == NULL) {
                        g_dbus_method_invocation_return_value(invocation,
                                        g_variant_new("(is)",
-                                               PKGMGR_R_ESYSTEM, ""));
+                                               PKGMGR_R_ENOPKG, ""));
                        free(reqkey);
                        return -1;
                }
@@ -660,7 +709,7 @@ static int __handle_request_disable_pkgs(uid_t caller_uid,
                if (pkgtype == NULL) {
                        g_dbus_method_invocation_return_value(invocation,
                                        g_variant_new("(is)",
-                                               PKGMGR_R_ESYSTEM, ""));
+                                               PKGMGR_R_ENOPKG, ""));
                        free(reqkey);
                        return -1;
                }
@@ -684,6 +733,91 @@ static int __handle_request_disable_pkgs(uid_t caller_uid,
        return 0;
 }
 
+static int __handle_request_enable_apps(uid_t caller_uid,
+               GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+       uid_t target_uid = (uid_t)-1;
+       char *appid;
+       char *reqkey;
+       char buf[MAX_PKG_ARGS_LEN];
+       GVariantIter *iter;
+
+       g_variant_get(parameters, "(uas)", &target_uid, &iter);
+       if (target_uid == (uid_t)-1 || iter == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+               return -1;
+       }
+
+       reqkey = __generate_reqkey("enable_apps");
+       if (reqkey == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(is)", PKGMGR_R_ENOMEM, ""));
+               return -1;
+       }
+
+       while (g_variant_iter_next(iter, "&s", &appid)) {
+               if (_push_queue(target_uid, caller_uid, reqkey,
+                                       REQUEST_TYPE_ENABLE_APP,
+                                       "default", appid, buf)) {
+                       g_dbus_method_invocation_return_value(invocation,
+                                       g_variant_new("(is)",
+                                               PKGMGR_R_ESYSTEM, ""));
+                       free(reqkey);
+                       return -1;
+               }
+       }
+
+       g_dbus_method_invocation_return_value(invocation,
+               g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+
+       free(reqkey);
+       return 0;
+}
+
+static int __handle_request_disable_apps(uid_t caller_uid,
+               GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+       uid_t target_uid = (uid_t)-1;
+       char *appid;
+       char *reqkey;
+       char buf[MAX_PKG_ARGS_LEN];
+       GVariantIter *iter;
+
+       g_variant_get(parameters, "(uas)", &target_uid, &iter);
+       if (target_uid == (uid_t)-1 || iter == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+               return -1;
+       }
+
+       reqkey = __generate_reqkey("disable_apps");
+       if (reqkey == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(is)", PKGMGR_R_ENOMEM, ""));
+               return -1;
+       }
+
+       while (g_variant_iter_next(iter, "&s", &appid)) {
+               if (_push_queue(target_uid, caller_uid, reqkey,
+                                       REQUEST_TYPE_DISABLE_APP,
+                                       "default", appid, buf)) {
+                       g_dbus_method_invocation_return_value(invocation,
+                                       g_variant_new("(is)",
+                                               PKGMGR_R_ESYSTEM, ""));
+                       free(reqkey);
+                       return -1;
+               }
+       }
+
+       g_dbus_method_invocation_return_value(invocation,
+               g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+
+       free(reqkey);
+       return 0;
+
+}
+
 static int __handle_request_enable_app(uid_t caller_uid,
                GDBusMethodInvocation *invocation, GVariant *parameters)
 {
@@ -899,51 +1033,68 @@ static int __handle_request_getsize(uid_t caller_uid,
        return 0;
 }
 
-static int __handle_request_cleardata(uid_t caller_uid,
+static int __handle_request_getsize_sync(uid_t caller_uid,
                GDBusMethodInvocation *invocation, GVariant *parameters)
 {
        uid_t target_uid = (uid_t)-1;
-       char *pkgtype;
        char *pkgid = NULL;
-       char *reqkey = NULL;
+       int get_type = -1;
+       char *reqkey;
+       char buf[4];
 
-       g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
-       if (target_uid == (uid_t)-1 || pkgid == NULL) {
+       g_variant_get(parameters, "(u&si)", &target_uid, &pkgid, &get_type);
+       if (target_uid == (uid_t)-1 || pkgid == NULL || get_type == -1) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(i)", PKGMGR_R_ECOMM));
+                               g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
                return -1;
        }
 
-       pkgtype = _get_pkgtype_from_pkgid(pkgid, target_uid);
-       if (pkgtype == NULL) {
+       reqkey = __generate_reqkey(pkgid);
+       if (reqkey == NULL) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+                               g_variant_new("(is)", PKGMGR_R_ENOMEM, ""));
                return -1;
        }
 
-       reqkey = __generate_reqkey(pkgid);
-       if (reqkey == NULL) {
+       snprintf(buf, sizeof(buf), "%d", get_type);
+       if (_push_queue(target_uid, caller_uid, reqkey, REQUEST_TYPE_GETSIZE_SYNC,
+                               "pkgtool", pkgid, buf)) {
                g_dbus_method_invocation_return_value(invocation,
-                               g_variant_new("(i)", PKGMGR_R_ENOMEM));
-               free(pkgtype);
+                               g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+               free(reqkey);
                return -1;
        }
 
-       if (_push_queue(target_uid, caller_uid, reqkey, REQUEST_TYPE_CLEARDATA,
-                               pkgtype, pkgid, NULL)) {
+       if (!g_hash_table_insert(req_table, (gpointer)reqkey,
+                               (gpointer)invocation))
+               ERR("reqkey already exists");
+
+       return 0;
+}
+
+static int __handle_request_cleardata(uid_t caller_uid,
+               GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+       uid_t target_uid = (uid_t)-1;
+       char *pkgid = NULL;
+
+       g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+       if (target_uid == (uid_t)-1 || pkgid == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ECOMM));
+               return -1;
+       }
+
+       if (_push_queue(target_uid, caller_uid, NULL, REQUEST_TYPE_CLEARDATA,
+                               "pkgtool", pkgid, NULL)) {
                g_dbus_method_invocation_return_value(invocation,
                                g_variant_new("(i)", PKGMGR_R_ESYSTEM));
-               free(reqkey);
-               free(pkgtype);
                return -1;
        }
 
        g_dbus_method_invocation_return_value(invocation,
                        g_variant_new("(i)", PKGMGR_R_OK));
 
-       free(reqkey);
-       free(pkgtype);
-
        return 0;
 }
 
@@ -1331,6 +1482,93 @@ static int __handle_request_get_restriction_mode(uid_t caller_uid,
        return 0;
 }
 
+static int __handle_request_set_app_label(uid_t uid,
+               GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+       uid_t target_uid = (uid_t)-1;
+       char *appid = NULL;
+       char *label = NULL;
+       char *reqkey;
+
+       g_variant_get(parameters, "(uss)", &target_uid, &appid, &label);
+       if (target_uid == (uid_t)-1 || appid == NULL || label == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ECOMM));
+               return -1;
+       }
+
+       reqkey = __generate_reqkey("appid");
+       if (reqkey == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ENOMEM));
+               return -1;
+       }
+
+       if (_push_queue(target_uid, uid, reqkey,
+                               REQUEST_TYPE_SET_APP_LABEL,
+                               "default", appid, label)) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+               free(reqkey);
+               return -1;
+       }
+
+       if (!g_hash_table_insert(req_table, (gpointer)reqkey,
+                               (gpointer)invocation))
+               ERR("reqkey already exists");
+
+       return 0;
+}
+
+static int __handle_request_migrate_external_image(uid_t uid,
+               GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+       uid_t target_uid = (uid_t)-1;
+       char *pkgid = NULL;
+       char *pkgtype;
+       char *reqkey;
+
+       g_variant_get(parameters, "(us)", &target_uid, &pkgid);
+       if (target_uid == (uid_t)-1 || pkgid == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ECOMM));
+               return -1;
+       }
+
+       pkgtype = _get_pkgtype_from_pkgid(pkgid, target_uid);
+       if (pkgtype == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ENOPKG));
+               return -1;
+       }
+
+       reqkey = __generate_reqkey(pkgid);
+       if (reqkey == NULL) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ENOMEM));
+               free(pkgtype);
+               return -1;
+       }
+
+       if (_push_queue(target_uid, uid, reqkey,
+                               REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE,
+                               pkgtype, pkgid, NULL)) {
+               g_dbus_method_invocation_return_value(invocation,
+                               g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+               free(reqkey);
+               free(pkgtype);
+               return -1;
+       }
+
+       g_dbus_method_invocation_return_value(invocation,
+                       g_variant_new("(i)", PKGMGR_R_OK));
+
+       free(reqkey);
+       free(pkgtype);
+
+       return 0;
+}
+
 static uid_t __get_caller_uid(GDBusConnection *connection, const char *name)
 {
        GError *err = NULL;
@@ -1349,6 +1587,7 @@ static uid_t __get_caller_uid(GDBusConnection *connection, const char *name)
        }
 
        g_variant_get(result, "(u)", &uid);
+       g_variant_unref(result);
 
        return uid;
 }
@@ -1389,12 +1628,18 @@ static void __handle_method_call(GDBusConnection *connection,
                ret = __handle_request_disable_pkgs(uid, invocation, parameters);
        else if (g_strcmp0(method_name, "getsize") == 0)
                ret = __handle_request_getsize(uid, invocation, parameters);
+       else if (g_strcmp0(method_name, "getsize_sync") == 0)
+               ret = __handle_request_getsize_sync(uid, invocation, parameters);
        else if (g_strcmp0(method_name, "clearcache") == 0)
                ret = __handle_request_clearcache(uid, invocation, parameters);
        else if (g_strcmp0(method_name, "enable_app") == 0)
                ret = __handle_request_enable_app(uid, invocation, parameters);
        else if (g_strcmp0(method_name, "disable_app") == 0)
                ret = __handle_request_disable_app(uid, invocation, parameters);
+       else if (g_strcmp0(method_name, "enable_apps") == 0)
+               ret = __handle_request_enable_apps(uid, invocation, parameters);
+       else if (g_strcmp0(method_name, "disable_apps") == 0)
+               ret = __handle_request_disable_apps(uid, invocation, parameters);
        else if (g_strcmp0(method_name, "enable_global_app_for_uid") == 0)
                ret = __handle_request_enable_global_app_for_uid(uid,
                                invocation, parameters);
@@ -1429,6 +1674,11 @@ static void __handle_method_call(GDBusConnection *connection,
        else if (g_strcmp0(method_name, "get_restriction_mode") == 0)
                ret = __handle_request_get_restriction_mode(uid, invocation,
                                parameters);
+       else if (g_strcmp0(method_name, "set_app_label") == 0)
+               ret = __handle_request_set_app_label(uid, invocation, parameters);
+       else if (g_strcmp0(method_name, "migrate_external_image") == 0)
+               ret = __handle_request_migrate_external_image(uid, invocation,
+                               parameters);
        else
                ret = -1;