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;
73 g_variant_ref_sink(param);
75 /* get gdbus connection */
76 ret = app2sd_gdbus_shared_connection(&conn);
78 _E("app2sd error : dbus connection error");
80 g_variant_unref(param);
86 proxy = g_dbus_proxy_new_sync(conn,
87 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
88 APP2SD_BUS_NAME, APP2SD_OBJECT_PATH,
89 APP2SD_INTERFACE_NAME,
92 _E("failed to create new proxy, error(%s)",
96 ret = APP2EXT_ERROR_DBUS_FAILED;
98 usleep(CONNECTION_WAIT_USEC);
102 value = g_dbus_proxy_call_sync(proxy, method_name, param,
103 G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, &error);
104 g_object_unref(proxy);
106 _E("proxy call sync error(%s)", error->message);
109 ret = APP2EXT_ERROR_DBUS_FAILED;
111 usleep(CONNECTION_WAIT_USEC);
115 g_variant_get(value, "(i)", &result);
116 g_variant_unref(value);
118 _D("result(%d)", result);
123 } while (retry_cnt <= CONNECTION_RETRY_MAX);
126 g_object_unref(conn);
128 g_variant_unref(param);
133 static void __app2sd_create_dir_list_builder(gpointer data, gpointer user_data)
135 app2ext_dir_details *item = (app2ext_dir_details *)data;
136 GVariantBuilder *builder = (GVariantBuilder *)user_data;
138 g_variant_builder_add(builder, "(si)", item->name, item->type);
141 static int __app2sd_delete_temp_directories(const char *pkgid,
142 app2sd_cmd cmd, uid_t uid)
145 char app_path[FILENAME_MAX] = { 0, };
146 char temp_path[FILENAME_MAX] = { 0, };
148 if (cmd != APP2SD_PRE_UPGRADE)
149 return APP2EXT_SUCCESS;
151 _app2sd_set_application_path(pkgid, uid, app_path, sizeof(app_path));
152 ret = snprintf(temp_path, sizeof(temp_path), "%s.new", app_path);
153 if (ret < 0 || ret > sizeof(temp_path)) {
155 return APP2EXT_ERROR_DELETE_DIRECTORY;
158 /* this will delete all files under temp_path */
159 ret = _app2sd_delete_directory(temp_path);
161 _E("unable to delete (%s)", temp_path);
162 return APP2EXT_ERROR_DELETE_DIRECTORY;
165 return APP2EXT_SUCCESS;
168 static int __app2sd_create_default_directories(const char *pkgid,
169 app2sd_cmd cmd, uid_t uid)
172 mode_t mode = DIR_PERMS;
173 char application_path[FILENAME_MAX] = { 0, };
174 char app_mmc_path[FILENAME_MAX] = { 0, };
175 char temp_path[FILENAME_MAX] = { 0, };
177 _app2sd_set_application_path(pkgid, uid, application_path,
178 sizeof(application_path));
179 ret = mkdir(application_path, mode);
181 if (errno != EEXIST) {
182 _E("create directory failed," \
183 " error no is (%d)", errno);
184 return APP2EXT_ERROR_CREATE_DIRECTORY;
188 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
190 if (ret < 0 || ret > sizeof(app_mmc_path)) {
192 return APP2EXT_ERROR_CREATE_DIRECTORY;
194 ret = mkdir(app_mmc_path, mode);
196 if (errno != EEXIST) {
197 _E("create directory failed," \
198 " error no is (%d)", errno);
199 return APP2EXT_ERROR_CREATE_DIRECTORY;
203 if (cmd == APP2SD_PRE_UPGRADE) {
204 /* application_path for {pkgid}.new */
205 ret = snprintf(temp_path, sizeof(temp_path), "%s.new",
207 if (ret < 0 || ret > sizeof(temp_path)) {
209 return APP2EXT_ERROR_CREATE_DIRECTORY;
211 ret = mkdir(temp_path, mode);
213 if (errno != EEXIST) {
214 _E("create directory failed," \
215 " error no is (%d)", errno);
216 return APP2EXT_ERROR_CREATE_DIRECTORY;
219 /* app_mmc_path for {pkgid}.new */
220 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
222 if (ret < 0 || ret > sizeof(app_mmc_path)) {
224 return APP2EXT_ERROR_CREATE_DIRECTORY;
226 ret = mkdir(app_mmc_path, mode);
228 if (errno != EEXIST) {
229 _E("create directory failed," \
230 " error no is (%d)", errno);
231 return APP2EXT_ERROR_CREATE_DIRECTORY;
236 return APP2EXT_SUCCESS;
239 int app2sd_client_usr_pre_app_install(const char *pkgid, GList *dir_list,
243 GVariantBuilder *builder = NULL;
244 GVariant *param = NULL;
246 /* validate the function parameter recieved */
247 if (pkgid == NULL || dir_list == NULL || size <= 0) {
248 _E("invalid function arguments");
249 return APP2EXT_ERROR_INVALID_ARGUMENTS;
252 ret = __app2sd_create_default_directories(pkgid,
253 APP2SD_PRE_INSTALL, uid);
257 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
258 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
260 param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
261 ret = __app2sd_call_server_method("PreAppInstall", param);
264 g_variant_builder_unref(builder);
268 int app2sd_client_pre_app_install(const char *pkgid, GList *dir_list,
273 ret = app2sd_client_usr_pre_app_install(pkgid,
274 dir_list, size, getuid());
279 int app2sd_client_usr_post_app_install(const char *pkgid,
280 app2ext_status install_status, uid_t uid)
283 GVariant *param = NULL;
285 /* validate the function parameter recieved */
286 if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
287 || install_status > APP2EXT_STATUS_SUCCESS) {
288 _E("invalid func parameters");
289 return APP2EXT_ERROR_INVALID_ARGUMENTS;
292 param = g_variant_new("(sii)", pkgid, install_status, uid);
293 ret = __app2sd_call_server_method("PostAppInstall", param);
297 int app2sd_client_post_app_install(const char *pkgid,
298 app2ext_status install_status)
302 ret = app2sd_client_usr_post_app_install(pkgid,
303 install_status, getuid());
308 int app2sd_client_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
312 GVariantBuilder *builder = NULL;
313 GVariant *param = NULL;
315 /* validate the function parameter recieved */
316 if (pkgid == NULL || dir_list == NULL || size <= 0) {
317 _E("invalid function arguments");
318 return APP2EXT_ERROR_INVALID_ARGUMENTS;
321 ret = __app2sd_create_default_directories(pkgid,
322 APP2SD_PRE_UPGRADE, uid);
326 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
327 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
329 param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
330 ret = __app2sd_call_server_method("PreAppUpgrade", param);
333 g_variant_builder_unref(builder);
335 __app2sd_delete_temp_directories(pkgid, APP2SD_PRE_UPGRADE, uid);
339 int app2sd_client_pre_app_upgrade(const char *pkgid, GList *dir_list,
344 ret = app2sd_client_usr_pre_app_upgrade(pkgid,
345 dir_list, size, getuid());
350 int app2sd_client_usr_post_app_upgrade(const char *pkgid,
351 app2ext_status install_status, uid_t uid)
354 GVariant *param = NULL;
356 /* validate the function parameter recieved */
357 if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
358 || install_status > APP2EXT_STATUS_SUCCESS) {
359 _E("invalid func parameters");
360 return APP2EXT_ERROR_INVALID_ARGUMENTS;
363 param = g_variant_new("(sii)", pkgid, install_status, uid);
364 ret = __app2sd_call_server_method("PostAppUpgrade", param);
368 int app2sd_client_post_app_upgrade(const char *pkgid,
369 app2ext_status install_status)
373 ret = app2sd_client_usr_post_app_upgrade(pkgid,
374 install_status, getuid());
379 int app2sd_client_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
382 GVariant *param = NULL;
384 /* validate the function parameter recieved */
386 _E("invalid func parameters");
387 return APP2EXT_ERROR_INVALID_ARGUMENTS;
390 param = g_variant_new("(si)", pkgid, uid);
391 ret = __app2sd_call_server_method("PreAppUninstall", param);
395 int app2sd_client_pre_app_uninstall(const char *pkgid)
399 ret = app2sd_client_usr_pre_app_uninstall(pkgid,
405 int app2sd_client_usr_post_app_uninstall(const char *pkgid, uid_t uid)
408 GVariant *param = NULL;
410 /* validate the function parameter recieved */
412 _E("invalid func parameters");
413 return APP2EXT_ERROR_INVALID_ARGUMENTS;
416 param = g_variant_new("(si)", pkgid, uid);
417 ret = __app2sd_call_server_method("PostAppUninstall", param);
421 int app2sd_client_post_app_uninstall(const char *pkgid)
425 ret = app2sd_client_usr_post_app_uninstall(pkgid,
431 int app2sd_client_usr_force_clean(const char *pkgid, uid_t uid)
434 GVariant *param = NULL;
436 /* validate the function parameter recieved */
438 _E("invalid func parameters");
439 return APP2EXT_ERROR_INVALID_ARGUMENTS;
442 param = g_variant_new("(si)", pkgid, uid);
443 ret = __app2sd_call_server_method("ForceClean", param);
447 int app2sd_client_force_clean(const char *pkgid)
451 ret = app2sd_client_usr_force_clean(pkgid, getuid());
456 int app2sd_client_enable_full_pkg(void)
460 ret = __app2sd_call_server_method("EnableFullPkg", NULL);
465 int app2sd_client_disable_full_pkg(void)
469 ret = __app2sd_call_server_method("DisableFullPkg", NULL);
474 int app2sd_client_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
477 GVariant *param = NULL;
479 /* validate the function parameter recieved */
481 _E("invalid func parameters");
482 return APP2EXT_ERROR_INVALID_ARGUMENTS;
485 param = g_variant_new("(si)", pkgid, uid);
486 ret = __app2sd_call_server_method("OndemandSetupInit", param);
490 int app2sd_client_on_demand_setup_init(const char *pkgid)
494 ret = app2sd_client_usr_on_demand_setup_init(pkgid,
500 int app2sd_client_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
503 GVariant *param = NULL;
505 /* validate the function parameter recieved */
507 _E("invalid func parameters");
508 return APP2EXT_ERROR_INVALID_ARGUMENTS;
511 param = g_variant_new("(si)", pkgid, uid);
512 ret = __app2sd_call_server_method("OndemandSetupExit", param);
516 int app2sd_client_on_demand_setup_exit(const char *pkgid)
520 ret = app2sd_client_usr_on_demand_setup_exit(pkgid,
526 int app2sd_client_usr_pre_move_installed_app(const char *pkgid, GList *dir_list,
527 app2ext_move_type move_type, uid_t uid)
530 GVariantBuilder *builder = NULL;
531 GVariant *param = NULL;
532 app2sd_cmd cmd = APP2SD_MOVE_APP_TO_PHONE;
533 pkgmgrinfo_pkginfo_h info_handle = NULL;
534 pkgmgrinfo_installed_storage storage = PMINFO_INTERNAL_STORAGE;
536 /* validate the function parameter recieved */
537 if (pkgid == NULL || dir_list == NULL
538 || move_type < APP2EXT_MOVE_TO_EXT
539 || move_type > APP2EXT_MOVE_TO_PHONE) {
540 _E("invalid function arguments");
541 return APP2EXT_ERROR_INVALID_ARGUMENTS;
544 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &info_handle);
546 _E("failed to get pkginfo for pkg(%s), uid(%d), ret(%d)",
548 return APP2EXT_ERROR_PKGMGR_ERROR;
550 ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
552 _E("failed to get installed storage for pkg(%s) " \
553 "of uid(%d), ret(%d)", pkgid, uid, ret);
554 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
555 return APP2EXT_ERROR_PKGMGR_ERROR;
558 if ((move_type == APP2EXT_MOVE_TO_EXT && storage ==
559 PMINFO_EXTERNAL_STORAGE)
560 || (move_type == APP2EXT_MOVE_TO_PHONE &&
561 storage == PMINFO_INTERNAL_STORAGE)) {
562 _E("PKG_EXISTS in [%d] STORAGE", storage);
563 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
564 return APP2EXT_ERROR_PKG_EXISTS;
566 _D("pkgid[%s] move to STORAGE [%d]", pkgid, storage);
568 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
570 if (move_type == APP2EXT_MOVE_TO_EXT)
571 cmd = APP2SD_MOVE_APP_TO_MMC;
573 if (cmd == APP2SD_MOVE_APP_TO_MMC) {
574 ret = __app2sd_create_default_directories(pkgid, cmd, uid);
579 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
580 g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
582 param = g_variant_new("(sia(si)i)", pkgid, move_type, builder, uid);
583 ret = __app2sd_call_server_method("PreMoveInstalledApp", param);
586 g_variant_builder_unref(builder);
590 int app2sd_client_pre_move_installed_app(const char *pkgid, GList *dir_list,
591 app2ext_move_type move_type)
595 ret = app2sd_client_usr_pre_move_installed_app(pkgid,
596 dir_list, move_type, getuid());
601 int app2sd_client_usr_post_move_installed_app(const char *pkgid,
602 app2ext_move_type move_type, uid_t uid)
605 GVariant *param = NULL;
607 /* validate the function parameter recieved */
608 if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
609 || move_type > APP2EXT_MOVE_TO_PHONE) {
610 _E("invalid function arguments");
611 return APP2EXT_ERROR_INVALID_ARGUMENTS;
614 param = g_variant_new("(sii)", pkgid, move_type, uid);
615 ret = __app2sd_call_server_method("PostMoveInstalledApp", param);
619 int app2sd_client_post_move_installed_app(const char *pkgid,
620 app2ext_move_type move_type)
624 ret = app2sd_client_usr_post_move_installed_app(pkgid,
625 move_type, getuid());
630 int app2sd_client_usr_pre_migrate_legacy(const char *pkgid, uid_t uid)
633 GVariant *param = NULL;
635 /* validate the function parameter recieved */
637 _E("invalid function arguments");
638 return APP2EXT_ERROR_INVALID_ARGUMENTS;
641 param = g_variant_new("(si)", pkgid, uid);
642 ret = __app2sd_call_server_method("PreMigrateLegacy", param);
647 int app2sd_client_usr_post_migrate_legacy(const char *pkgid, uid_t uid)
650 GVariant *param = NULL;
652 /* validate the function parameter recieved */
654 _E("invalid function arguments");
655 return APP2EXT_ERROR_INVALID_ARGUMENTS;
658 param = g_variant_new("(si)", pkgid, uid);
659 ret = __app2sd_call_server_method("PostMigrateLegacy", param);
664 int app2sd_client_migrate_legacy_all()
668 ret = __app2sd_call_server_method("MigrateLegacyAll", NULL);
673 char *app2sd_client_usr_getname_image(const char *pkgid, uid_t uid)
675 return _app2sd_get_encoded_name(pkgid, uid);
678 char *app2sd_client_usr_get_image_path(const char *pkgid, uid_t uid)
680 static const char query[] =
681 "SELECT filename FROM app2sd_info WHERE pkgid=? AND uid=?";
686 char *image_path = NULL;
688 dbpath = tzplatform_mkpath(TZ_SYS_DB, ".app2sd.db");
692 ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
693 if (ret != SQLITE_OK) {
694 LOGE("open failed: %s", sqlite3_errmsg(db));
695 sqlite3_close_v2(db);
699 ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
700 if (ret != SQLITE_OK) {
701 LOGE("prepare failed: %s", sqlite3_errmsg(db));
702 sqlite3_close_v2(db);
706 ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
707 if (ret != SQLITE_OK) {
708 LOGE("bind failed: %s", sqlite3_errmsg(db));
709 sqlite3_finalize(stmt);
710 sqlite3_close_v2(db);
714 ret = sqlite3_bind_int(stmt, 2, uid);
715 if (ret != SQLITE_OK) {
716 LOGE("bind failed: %s", sqlite3_errmsg(db));
717 sqlite3_finalize(stmt);
718 sqlite3_close_v2(db);
722 ret = sqlite3_step(stmt);
723 if (ret == SQLITE_ROW)
724 image_path = strdup((char *)sqlite3_column_text(stmt, 0));
726 sqlite3_finalize(stmt);
727 sqlite3_close_v2(db);
732 void app2ext_on_load(app2ext_interface *interface)
734 /* Plug-in Binding.*/
735 interface->client_pre_install = app2sd_client_pre_app_install;
736 interface->client_post_install = app2sd_client_post_app_install;
737 interface->client_pre_upgrade = app2sd_client_pre_app_upgrade;
738 interface->client_post_upgrade = app2sd_client_post_app_upgrade;
739 interface->client_pre_uninstall = app2sd_client_pre_app_uninstall;
740 interface->client_post_uninstall = app2sd_client_post_app_uninstall;
741 interface->client_force_clean = app2sd_client_force_clean;
742 interface->client_enable = app2sd_client_on_demand_setup_init;
743 interface->client_disable = app2sd_client_on_demand_setup_exit;
744 interface->client_enable_full_pkg = app2sd_client_enable_full_pkg;
745 interface->client_disable_full_pkg = app2sd_client_disable_full_pkg;
746 interface->client_pre_move = app2sd_client_pre_move_installed_app;
747 interface->client_post_move = app2sd_client_post_move_installed_app;
748 interface->client_migrate_legacy_all = app2sd_client_migrate_legacy_all;
750 interface->client_usr_pre_install = app2sd_client_usr_pre_app_install;
751 interface->client_usr_post_install = app2sd_client_usr_post_app_install;
752 interface->client_usr_pre_upgrade = app2sd_client_usr_pre_app_upgrade;
753 interface->client_usr_post_upgrade = app2sd_client_usr_post_app_upgrade;
754 interface->client_usr_pre_uninstall = app2sd_client_usr_pre_app_uninstall;
755 interface->client_usr_post_uninstall = app2sd_client_usr_post_app_uninstall;
756 interface->client_usr_force_clean = app2sd_client_usr_force_clean;
757 interface->client_usr_enable = app2sd_client_usr_on_demand_setup_init;
758 interface->client_usr_disable = app2sd_client_usr_on_demand_setup_exit;
759 interface->client_usr_pre_move = app2sd_client_usr_pre_move_installed_app;
760 interface->client_usr_post_move = app2sd_client_usr_post_move_installed_app;
761 interface->client_usr_getname_image = app2sd_client_usr_getname_image;
762 interface->client_usr_pre_migrate_legacy = app2sd_client_usr_pre_migrate_legacy;
763 interface->client_usr_post_migrate_legacy = app2sd_client_usr_post_migrate_legacy;
764 interface->client_usr_get_image_path = app2sd_client_usr_get_image_path;