4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Garima Shrivastava<garima.s@samsung.com>
7 * Jyotsna Dhumale <jyotsna.a@samsung.com>
8 * Venkatesha Sarpangala <sarpangala.v@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
26 #include <sys/types.h>
30 #include <pkgmgr-info.h>
32 #include <tzplatform_config.h>
34 #include "app2sd_client_interface.h"
35 #include "app2sd_utils.h"
37 #define CONNECTION_RETRY_MAX 5
38 #define CONNECTION_WAIT_USEC (1000000 / 2) /* 0.5 sec */
40 static int app2sd_gdbus_shared_connection(GDBusConnection **connection)
44 #if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36)
48 *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
49 if (*connection == NULL) {
51 _E("app2sd error : failed to get "
52 "system dbus [%s]", error->message);
55 return APP2EXT_ERROR_DBUS_FAILED;
58 return APP2EXT_SUCCESS;
61 static int __app2sd_call_server_method(const gchar *method_name,
64 int ret = APP2EXT_SUCCESS;
67 GDBusConnection *conn = NULL;
68 GDBusProxy *proxy = NULL;
70 GVariant *value = NULL;
72 /* get gdbus connection */
73 ret = app2sd_gdbus_shared_connection(&conn);
75 _E("app2sd error : dbus connection error");
81 proxy = g_dbus_proxy_new_sync(conn,
82 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
83 APP2SD_BUS_NAME, APP2SD_OBJECT_PATH,
84 APP2SD_INTERFACE_NAME,
87 _E("failed to create new proxy, error(%s)",
91 ret = APP2EXT_ERROR_DBUS_FAILED;
93 usleep(CONNECTION_WAIT_USEC);
97 value = g_dbus_proxy_call_sync(proxy, method_name, param,
98 G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, &error);
99 g_object_unref(proxy);
101 _E("proxy call sync error(%s)", error->message);
104 ret = APP2EXT_ERROR_DBUS_FAILED;
106 usleep(CONNECTION_WAIT_USEC);
110 g_variant_get(value, "(i)", &result);
111 g_variant_unref(value);
113 _D("result(%d)", result);
118 } while (retry_cnt <= CONNECTION_RETRY_MAX);
121 g_object_unref(conn);
126 static void __app2sd_create_dir_list_builder(gpointer data, gpointer user_data)
128 app2ext_dir_details *item = (app2ext_dir_details *)data;
129 GVariantBuilder *builder = (GVariantBuilder *)user_data;
131 g_variant_builder_add(builder, "(si)", item->name, item->type);
134 static int __app2sd_delete_temp_directories(const char *pkgid,
135 app2sd_cmd cmd, uid_t uid)
138 char app_path[FILENAME_MAX] = { 0, };
139 char temp_path[FILENAME_MAX] = { 0, };
141 if (cmd != APP2SD_PRE_UPGRADE)
142 return APP2EXT_SUCCESS;
144 _app2sd_set_application_path(pkgid, uid, app_path, sizeof(app_path));
145 ret = snprintf(temp_path, sizeof(temp_path), "%s.new", app_path);
146 if (ret < 0 || ret > sizeof(temp_path)) {
148 return APP2EXT_ERROR_DELETE_DIRECTORY;
151 /* this will delete all files under temp_path */
152 ret = _app2sd_delete_directory(temp_path);
154 _E("unable to delete (%s)", temp_path);
155 return APP2EXT_ERROR_DELETE_DIRECTORY;
158 return APP2EXT_SUCCESS;
161 static int __app2sd_create_default_directories(const char *pkgid,
162 app2sd_cmd cmd, uid_t uid)
165 mode_t mode = DIR_PERMS;
166 char application_path[FILENAME_MAX] = { 0, };
167 char app_mmc_path[FILENAME_MAX] = { 0, };
168 char temp_path[FILENAME_MAX] = { 0, };
170 _app2sd_set_application_path(pkgid, uid, application_path,
171 sizeof(application_path));
172 ret = mkdir(application_path, mode);
174 if (errno != EEXIST) {
175 _E("create directory failed," \
176 " error no is (%d)", errno);
177 return APP2EXT_ERROR_CREATE_DIRECTORY;
181 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
183 if (ret < 0 || ret > sizeof(app_mmc_path)) {
185 return APP2EXT_ERROR_CREATE_DIRECTORY;
187 ret = mkdir(app_mmc_path, mode);
189 if (errno != EEXIST) {
190 _E("create directory failed," \
191 " error no is (%d)", errno);
192 return APP2EXT_ERROR_CREATE_DIRECTORY;
196 if (cmd == APP2SD_PRE_UPGRADE) {
197 /* application_path for {pkgid}.new */
198 ret = snprintf(temp_path, sizeof(temp_path), "%s.new",
200 if (ret < 0 || ret > sizeof(temp_path)) {
202 return APP2EXT_ERROR_CREATE_DIRECTORY;
204 ret = mkdir(temp_path, mode);
206 if (errno != EEXIST) {
207 _E("create directory failed," \
208 " error no is (%d)", errno);
209 return APP2EXT_ERROR_CREATE_DIRECTORY;
212 /* app_mmc_path for {pkgid}.new */
213 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
215 if (ret < 0 || ret > sizeof(app_mmc_path)) {
217 return APP2EXT_ERROR_CREATE_DIRECTORY;
219 ret = mkdir(app_mmc_path, mode);
221 if (errno != EEXIST) {
222 _E("create directory failed," \
223 " error no is (%d)", errno);
224 return APP2EXT_ERROR_CREATE_DIRECTORY;
229 return APP2EXT_SUCCESS;
232 int app2sd_client_usr_pre_app_install(const char *pkgid, GList *dir_list,
236 GVariantBuilder *builder = NULL;
237 GVariant *param = NULL;
239 /* validate the function parameter recieved */
240 if (pkgid == NULL || dir_list == NULL || size <= 0) {
241 _E("invalid function arguments");
242 return APP2EXT_ERROR_INVALID_ARGUMENTS;
245 ret = __app2sd_create_default_directories(pkgid,
246 APP2SD_PRE_INSTALL, uid);
250 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
251 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
253 param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
254 ret = __app2sd_call_server_method("PreAppInstall", param);
257 g_variant_builder_unref(builder);
261 int app2sd_client_pre_app_install(const char *pkgid, GList *dir_list,
266 ret = app2sd_client_usr_pre_app_install(pkgid,
267 dir_list, size, getuid());
272 int app2sd_client_usr_post_app_install(const char *pkgid,
273 app2ext_status install_status, uid_t uid)
276 GVariant *param = NULL;
278 /* validate the function parameter recieved */
279 if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
280 || install_status > APP2EXT_STATUS_SUCCESS) {
281 _E("invalid func parameters");
282 return APP2EXT_ERROR_INVALID_ARGUMENTS;
285 param = g_variant_new("(sii)", pkgid, install_status, uid);
286 ret = __app2sd_call_server_method("PostAppInstall", param);
290 int app2sd_client_post_app_install(const char *pkgid,
291 app2ext_status install_status)
295 ret = app2sd_client_usr_post_app_install(pkgid,
296 install_status, getuid());
301 int app2sd_client_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
305 GVariantBuilder *builder = NULL;
306 GVariant *param = NULL;
308 /* validate the function parameter recieved */
309 if (pkgid == NULL || dir_list == NULL || size <= 0) {
310 _E("invalid function arguments");
311 return APP2EXT_ERROR_INVALID_ARGUMENTS;
314 ret = __app2sd_create_default_directories(pkgid,
315 APP2SD_PRE_UPGRADE, uid);
319 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
320 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
322 param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
323 ret = __app2sd_call_server_method("PreAppUpgrade", param);
326 g_variant_builder_unref(builder);
328 __app2sd_delete_temp_directories(pkgid, APP2SD_PRE_UPGRADE, uid);
332 int app2sd_client_pre_app_upgrade(const char *pkgid, GList *dir_list,
337 ret = app2sd_client_usr_pre_app_upgrade(pkgid,
338 dir_list, size, getuid());
343 int app2sd_client_usr_post_app_upgrade(const char *pkgid,
344 app2ext_status install_status, uid_t uid)
347 GVariant *param = NULL;
349 /* validate the function parameter recieved */
350 if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
351 || install_status > APP2EXT_STATUS_SUCCESS) {
352 _E("invalid func parameters");
353 return APP2EXT_ERROR_INVALID_ARGUMENTS;
356 param = g_variant_new("(sii)", pkgid, install_status, uid);
357 ret = __app2sd_call_server_method("PostAppUpgrade", param);
361 int app2sd_client_post_app_upgrade(const char *pkgid,
362 app2ext_status install_status)
366 ret = app2sd_client_usr_post_app_upgrade(pkgid,
367 install_status, getuid());
372 int app2sd_client_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
375 GVariant *param = NULL;
377 /* validate the function parameter recieved */
379 _E("invalid func parameters");
380 return APP2EXT_ERROR_INVALID_ARGUMENTS;
383 param = g_variant_new("(si)", pkgid, uid);
384 ret = __app2sd_call_server_method("PreAppUninstall", param);
388 int app2sd_client_pre_app_uninstall(const char *pkgid)
392 ret = app2sd_client_usr_pre_app_uninstall(pkgid,
398 int app2sd_client_usr_post_app_uninstall(const char *pkgid, uid_t uid)
401 GVariant *param = NULL;
403 /* validate the function parameter recieved */
405 _E("invalid func parameters");
406 return APP2EXT_ERROR_INVALID_ARGUMENTS;
409 param = g_variant_new("(si)", pkgid, uid);
410 ret = __app2sd_call_server_method("PostAppUninstall", param);
414 int app2sd_client_post_app_uninstall(const char *pkgid)
418 ret = app2sd_client_usr_post_app_uninstall(pkgid,
424 int app2sd_client_usr_force_clean(const char *pkgid, uid_t uid)
427 GVariant *param = NULL;
429 /* validate the function parameter recieved */
431 _E("invalid func parameters");
432 return APP2EXT_ERROR_INVALID_ARGUMENTS;
435 param = g_variant_new("(si)", pkgid, uid);
436 ret = __app2sd_call_server_method("ForceClean", param);
440 int app2sd_client_force_clean(const char *pkgid)
444 ret = app2sd_client_usr_force_clean(pkgid, getuid());
449 int app2sd_client_enable_full_pkg(void)
453 ret = __app2sd_call_server_method("EnableFullPkg", NULL);
458 int app2sd_client_disable_full_pkg(void)
462 ret = __app2sd_call_server_method("DisableFullPkg", NULL);
467 int app2sd_client_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
470 GVariant *param = NULL;
472 /* validate the function parameter recieved */
474 _E("invalid func parameters");
475 return APP2EXT_ERROR_INVALID_ARGUMENTS;
478 param = g_variant_new("(si)", pkgid, uid);
479 ret = __app2sd_call_server_method("OndemandSetupInit", param);
483 int app2sd_client_on_demand_setup_init(const char *pkgid)
487 ret = app2sd_client_usr_on_demand_setup_init(pkgid,
493 int app2sd_client_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
496 GVariant *param = NULL;
498 /* validate the function parameter recieved */
500 _E("invalid func parameters");
501 return APP2EXT_ERROR_INVALID_ARGUMENTS;
504 param = g_variant_new("(si)", pkgid, uid);
505 ret = __app2sd_call_server_method("OndemandSetupExit", param);
509 int app2sd_client_on_demand_setup_exit(const char *pkgid)
513 ret = app2sd_client_usr_on_demand_setup_exit(pkgid,
519 int app2sd_client_usr_pre_move_installed_app(const char *pkgid, GList *dir_list,
520 app2ext_move_type move_type, uid_t uid)
523 GVariantBuilder *builder = NULL;
524 GVariant *param = NULL;
525 app2sd_cmd cmd = APP2SD_MOVE_APP_TO_PHONE;
526 pkgmgrinfo_pkginfo_h info_handle = NULL;
527 pkgmgrinfo_installed_storage storage = PMINFO_INTERNAL_STORAGE;
529 /* validate the function parameter recieved */
530 if (pkgid == NULL || dir_list == NULL
531 || move_type < APP2EXT_MOVE_TO_EXT
532 || move_type > APP2EXT_MOVE_TO_PHONE) {
533 _E("invalid function arguments");
534 return APP2EXT_ERROR_INVALID_ARGUMENTS;
537 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &info_handle);
539 _E("failed to get pkginfo for pkg(%s), uid(%d), ret(%d)",
541 return APP2EXT_ERROR_PKGMGR_ERROR;
543 ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
545 _E("failed to get installed storage for pkg(%s) " \
546 "of uid(%d), ret(%d)", pkgid, uid, ret);
547 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
548 return APP2EXT_ERROR_PKGMGR_ERROR;
551 if ((move_type == APP2EXT_MOVE_TO_EXT && storage ==
552 PMINFO_EXTERNAL_STORAGE)
553 || (move_type == APP2EXT_MOVE_TO_PHONE &&
554 storage == PMINFO_INTERNAL_STORAGE)) {
555 _E("PKG_EXISTS in [%d] STORAGE", storage);
556 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
557 return APP2EXT_ERROR_PKG_EXISTS;
559 _D("pkgid[%s] move to STORAGE [%d]", pkgid, storage);
561 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
563 if (move_type == APP2EXT_MOVE_TO_EXT)
564 cmd = APP2SD_MOVE_APP_TO_MMC;
566 if (cmd == APP2SD_MOVE_APP_TO_MMC) {
567 ret = __app2sd_create_default_directories(pkgid, cmd, uid);
572 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
573 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
575 param = g_variant_new("(sia(si)i)", pkgid, move_type, builder, uid);
576 ret = __app2sd_call_server_method("PreMoveInstalledApp", param);
579 g_variant_builder_unref(builder);
583 int app2sd_client_pre_move_installed_app(const char *pkgid, GList *dir_list,
584 app2ext_move_type move_type)
588 ret = app2sd_client_usr_pre_move_installed_app(pkgid,
589 dir_list, move_type, getuid());
594 int app2sd_client_usr_post_move_installed_app(const char *pkgid,
595 app2ext_move_type move_type, uid_t uid)
598 GVariant *param = NULL;
600 /* validate the function parameter recieved */
601 if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
602 || move_type > APP2EXT_MOVE_TO_PHONE) {
603 _E("invalid function arguments");
604 return APP2EXT_ERROR_INVALID_ARGUMENTS;
607 param = g_variant_new("(sii)", pkgid, move_type, uid);
608 ret = __app2sd_call_server_method("PostMoveInstalledApp", param);
612 int app2sd_client_post_move_installed_app(const char *pkgid,
613 app2ext_move_type move_type)
617 ret = app2sd_client_usr_post_move_installed_app(pkgid,
618 move_type, getuid());
623 int app2sd_client_usr_pre_migrate_legacy(const char *pkgid, uid_t uid)
626 GVariant *param = NULL;
628 /* validate the function parameter recieved */
630 _E("invalid function arguments");
631 return APP2EXT_ERROR_INVALID_ARGUMENTS;
634 param = g_variant_new("(si)", pkgid, uid);
635 ret = __app2sd_call_server_method("PreMigrateLegacy", param);
640 int app2sd_client_usr_post_migrate_legacy(const char *pkgid, uid_t uid)
643 GVariant *param = NULL;
645 /* validate the function parameter recieved */
647 _E("invalid function arguments");
648 return APP2EXT_ERROR_INVALID_ARGUMENTS;
651 param = g_variant_new("(si)", pkgid, uid);
652 ret = __app2sd_call_server_method("PostMigrateLegacy", param);
657 int app2sd_client_migrate_legacy_all()
661 ret = __app2sd_call_server_method("MigrateLegacyAll", NULL);
666 char *app2sd_client_usr_getname_image(const char *pkgid, uid_t uid)
668 return _app2sd_get_encoded_name(pkgid, uid);
671 char *app2sd_client_usr_get_image_path(const char *pkgid, uid_t uid)
673 static const char query[] =
674 "SELECT filename FROM app2sd_info WHERE pkgid=? AND uid=?";
679 char *image_path = NULL;
681 dbpath = tzplatform_mkpath(TZ_SYS_DB, ".app2sd.db");
685 ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
686 if (ret != SQLITE_OK) {
687 LOGE("open failed: %s", sqlite3_errmsg(db));
688 sqlite3_close_v2(db);
692 ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
693 if (ret != SQLITE_OK) {
694 LOGE("prepare failed: %s", sqlite3_errmsg(db));
695 sqlite3_close_v2(db);
699 ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
700 if (ret != SQLITE_OK) {
701 LOGE("bind failed: %s", sqlite3_errmsg(db));
702 sqlite3_finalize(stmt);
703 sqlite3_close_v2(db);
707 ret = sqlite3_bind_int(stmt, 2, uid);
708 if (ret != SQLITE_OK) {
709 LOGE("bind failed: %s", sqlite3_errmsg(db));
710 sqlite3_finalize(stmt);
711 sqlite3_close_v2(db);
715 ret = sqlite3_step(stmt);
716 if (ret == SQLITE_ROW)
717 image_path = strdup((char *)sqlite3_column_text(stmt, 0));
719 sqlite3_finalize(stmt);
720 sqlite3_close_v2(db);
725 void app2ext_on_load(app2ext_interface *interface)
727 /* Plug-in Binding.*/
728 interface->client_pre_install = app2sd_client_pre_app_install;
729 interface->client_post_install = app2sd_client_post_app_install;
730 interface->client_pre_upgrade = app2sd_client_pre_app_upgrade;
731 interface->client_post_upgrade = app2sd_client_post_app_upgrade;
732 interface->client_pre_uninstall = app2sd_client_pre_app_uninstall;
733 interface->client_post_uninstall = app2sd_client_post_app_uninstall;
734 interface->client_force_clean = app2sd_client_force_clean;
735 interface->client_enable = app2sd_client_on_demand_setup_init;
736 interface->client_disable = app2sd_client_on_demand_setup_exit;
737 interface->client_enable_full_pkg = app2sd_client_enable_full_pkg;
738 interface->client_disable_full_pkg = app2sd_client_disable_full_pkg;
739 interface->client_pre_move = app2sd_client_pre_move_installed_app;
740 interface->client_post_move = app2sd_client_post_move_installed_app;
741 interface->client_migrate_legacy_all = app2sd_client_migrate_legacy_all;
743 interface->client_usr_pre_install = app2sd_client_usr_pre_app_install;
744 interface->client_usr_post_install = app2sd_client_usr_post_app_install;
745 interface->client_usr_pre_upgrade = app2sd_client_usr_pre_app_upgrade;
746 interface->client_usr_post_upgrade = app2sd_client_usr_post_app_upgrade;
747 interface->client_usr_pre_uninstall = app2sd_client_usr_pre_app_uninstall;
748 interface->client_usr_post_uninstall = app2sd_client_usr_post_app_uninstall;
749 interface->client_usr_force_clean = app2sd_client_usr_force_clean;
750 interface->client_usr_enable = app2sd_client_usr_on_demand_setup_init;
751 interface->client_usr_disable = app2sd_client_usr_on_demand_setup_exit;
752 interface->client_usr_pre_move = app2sd_client_usr_pre_move_installed_app;
753 interface->client_usr_post_move = app2sd_client_usr_post_move_installed_app;
754 interface->client_usr_getname_image = app2sd_client_usr_getname_image;
755 interface->client_usr_pre_migrate_legacy = app2sd_client_usr_pre_migrate_legacy;
756 interface->client_usr_post_migrate_legacy = app2sd_client_usr_post_migrate_legacy;
757 interface->client_usr_get_image_path = app2sd_client_usr_get_image_path;