4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
29 #include <sys/types.h>
32 #include <sys/types.h>
33 #include <sys/signalfd.h>
42 #include <pkgmgr-info.h>
43 #include <pkgmgr/pkgmgr_parser_db.h>
44 #include <tzplatform_config.h>
45 #include <drm-tizen-apps.h>
46 #include <dd-display.h>
47 #ifdef TIZEN_FEATURE_CSR
48 #include <csr-content-screening.h>
51 #include "pkgmgr_installer.h"
52 #include "pkgmgr-server.h"
54 #include "package-manager.h"
57 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
61 #define EXT_STORAGE_GROUP 10001
62 #define EXT_STORAGE_APPDATA_GROUP 10002
63 #define MEDIA_STORAGE_GROUP 10502
64 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
65 #define MAX_LONGLONG_LENGTH 32
80 8 bit value to represent maximum 8 backends.
81 Each bit position corresponds to a queue slot which
82 is dynamically determined.
84 static char backend_busy = 0;
85 extern int num_of_backends;
86 bool is_drm_busy = false;
87 static bool is_lock_set = false;
89 static GIOChannel *sio;
91 static GHashTable *backend_info_table;
92 static GMainLoop *mainloop;
94 static int __check_backend_status_for_exit(void);
95 static int __check_queue_status_for_exit(void);
96 static int __is_backend_busy(int position);
97 static void __set_backend_busy(int position);
98 static void __set_backend_free(int position);
100 gboolean exit_server(void *data);
102 /* To check whether a particular backend is free/busy */
103 static int __is_backend_busy(int position)
105 return backend_busy & (1 << position);
107 /* To set a particular backend as busy */
108 static void __set_backend_busy(int position)
110 backend_busy = backend_busy | (1 << position);
112 /* To set a particular backend as free */
113 static void __set_backend_free(int position)
115 backend_busy = backend_busy & ~(1 << position);
118 static void __set_power_lock(void)
123 if (display_lock_state(LCD_OFF, STAY_CUR_STATE, 0) == 0)
127 static void __release_power_lock(void)
132 if (display_unlock_state(LCD_OFF, PM_SLEEP_MARGIN) == 0)
136 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
142 char buf[MAX_LONGLONG_LENGTH];
143 long long result = 0;
144 struct backend_job *job = (struct backend_job *)data;
145 struct getsize_sync_extra_info *extra_getsize_info =
146 (struct getsize_sync_extra_info *)job->extra_data;
148 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
149 if (s != G_IO_STATUS_NORMAL) {
150 ERR("getsize fd read failed: %s", err->message);
154 if (strlen(buf) == 0) {
162 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
163 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
165 unlink(extra_getsize_info->getsize_fifo);
166 free(extra_getsize_info->getsize_fifo);
167 extra_getsize_info->getsize_fifo = NULL;
172 static int __setup_size_info_io(struct backend_job *job)
175 struct getsize_sync_extra_info *extra_getsize_info =
176 (struct getsize_sync_extra_info *)job->extra_data;
178 extra_getsize_info->getsize_fd = open(extra_getsize_info->getsize_fifo,
179 O_RDONLY | O_NONBLOCK);
180 if (extra_getsize_info->getsize_fd < 0) {
181 ERR("failed to open the fifo(%s), errno(%d)",
182 extra_getsize_info->getsize_fifo, errno);
186 extra_getsize_info->getsize_io =
187 g_io_channel_unix_new(extra_getsize_info->getsize_fd);
188 if (!extra_getsize_info->getsize_io)
190 g_io_channel_set_encoding(extra_getsize_info->getsize_io, NULL, NULL);
191 g_io_channel_set_buffered(extra_getsize_info->getsize_io, FALSE);
192 getsize_wid = g_io_add_watch_full(extra_getsize_info->getsize_io,
193 G_PRIORITY_HIGH, G_IO_IN, getsize_io_handler, job, NULL);
195 ERR("failed to add io watch");
202 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
208 struct signalfd_siginfo fdsi;
209 struct backend_job *job;
210 struct getsize_sync_extra_info *extra_getsize_info;
214 s = g_io_channel_read_chars(io, (gchar *)&fdsi,
215 sizeof(struct signalfd_siginfo), &len, &err);
216 if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
217 ERR("Signal read failed");
222 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
223 job = (struct backend_job *)g_hash_table_lookup(
224 backend_info_table, (gconstpointer)pid);
226 ERR("Unknown child exit");
230 __set_backend_free(job->backend_slot);
231 if (WIFSIGNALED(status)) {
232 _send_fail_signal(job);
233 INFO("backend[%s][%d] exit with signal[%d]",
234 job->backend_type, pid, WTERMSIG(status));
235 } else if (WEXITSTATUS(status)) {
236 INFO("backend[%s][%d] exit with error",
237 job->backend_type, pid);
239 INFO("backend[%s][%d] exit", job->backend_type, pid);
242 if (job->req_type == REQUEST_TYPE_GETSIZE_SYNC &&
245 (struct getsize_sync_extra_info *)job->extra_data;
246 if (extra_getsize_info->getsize_fifo) {
247 ERR("invalid backend close");
248 _return_value_to_caller(job->req_id,
249 g_variant_new("(ix)",
250 PKGMGR_R_ERROR, -1));
253 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
255 g_idle_add(queue_job, NULL);
260 static int __init_backend_info(void)
262 backend_info_table = g_hash_table_new_full(g_direct_hash,
263 g_direct_equal, NULL,
264 (GDestroyNotify)_free_backend_job);
269 static void __fini_backend_info(void)
271 /*Free backend info */
272 g_hash_table_destroy(backend_info_table);
275 static int __register_signal_handler(void)
281 sigaddset(&mask, SIGCHLD);
283 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
284 ERR("sigprocmask failed");
288 sfd = signalfd(-1, &mask, SFD_NONBLOCK);
290 ERR("signalfd failed");
294 sio = g_io_channel_unix_new(sfd);
295 g_io_channel_set_close_on_unref(sio, TRUE);
296 g_io_channel_set_encoding(sio, NULL, NULL);
297 g_io_channel_set_buffered(sio, FALSE);
298 swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
300 g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, exit_server, NULL, NULL);
305 static int __check_backend_status_for_exit(void)
308 for (i = 0; i < num_of_backends; i++) {
309 if (__is_backend_busy(i))
315 static int __check_queue_status_for_exit(void)
318 for (i = 0; i < num_of_backends; i++) {
319 if (_is_queue_empty(i) == 0)
325 gboolean exit_server(void *data)
327 DBG("exit_server Start");
328 if (__check_backend_status_for_exit() &&
329 __check_queue_status_for_exit() && !is_drm_busy) {
330 g_main_loop_quit(mainloop);
332 __release_power_lock();
338 #ifdef TIZEN_FEATURE_CSR
339 static int __check_csr(const char *path)
341 csr_cs_context_h context = NULL;
342 csr_cs_malware_h detected = NULL;
345 ret = csr_cs_context_create(&context);
346 if (ret != CSR_ERROR_NONE) {
347 ERR("Failed to create csr context");
352 ret = csr_cs_scan_file(context, path, &detected);
353 DBG("CSR result[%d]", ret);
355 csr_cs_context_destroy(context);
356 if (detected != NULL) {
357 ERR("CSR Denied[%s] Installation", path);
366 static int __kill_app(char *appid, uid_t uid)
372 is_running = aul_app_is_running_for_uid(appid, uid);
373 /* app is not running */
377 pid = aul_app_get_pid_for_uid(appid, uid);
381 ret = aul_terminate_pid_for_uid(pid, uid);
382 if (ret != AUL_R_OK) {
383 ERR("failed to terminate app(%d)", appid);
390 static int __check_app(char *appid, uid_t uid)
395 is_running = aul_app_is_running_for_uid(appid, uid);
399 pid = aul_app_get_pid_for_uid(appid, uid);
404 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
410 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
412 if (handle == NULL) {
413 perror("appinfo handle is NULL\n");
416 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
418 perror("Failed to get app exec path\n");
421 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
423 perror("Failed to get appid\n");
426 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
428 perror("Failed to get pkgid\n");
432 if (strcmp(pdata->cmd, "kill") == 0) {
433 pdata->pid = __check_app(appid, pdata->uid);
435 ret = __kill_app(appid, pdata->uid);
436 } else if (strcmp(pdata->cmd, "check") == 0) {
437 pdata->pid = __check_app(appid, pdata->uid);
443 void free_user_context(user_ctx *ctx)
450 /* env variable ends by NULL element */
460 int set_environement(user_ctx *ctx)
471 if (ctx->uid != APPFW_UID) {
472 if (setuid(ctx->uid)) {
473 ERR("setuid failed: %d", errno);
477 if (setgid(ctx->gid)) {
478 ERR("setgid failed: %d", errno);
483 n = getgroups(0, NULL);
485 ERR("Failed to get the number of supplementary group IDs");
489 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
490 if (groups == NULL) {
491 ERR("out of memory");
495 n = getgroups(n, groups);
497 ERR("Failed to get list of supplementary group IDs");
502 groups[n++] = EXT_STORAGE_GROUP;
503 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
504 groups[n++] = MEDIA_STORAGE_GROUP;
506 if (setgroups(n, groups) < 0) {
507 ERR("setgroups failed: %d", errno);
514 /* env variable ends by NULL element */
516 if (putenv(env[i]) != 0)
523 user_ctx *get_user_context(uid_t uid)
525 /* we can use getpwnam because this is used only after a
526 * fork and just before an execv
527 * No concurrencial call can corrupt the data
528 * returned by getpwuid
530 user_ctx *context_res;
532 char buf[1024] = {0, };
533 struct passwd pwd, *result;
538 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
539 if (ret != 0 || result == NULL)
543 context_res = (user_ctx *)malloc(sizeof(user_ctx));
548 env = (char **)malloc(3 * sizeof(char *));
553 /* Build environment context */
554 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
555 env[0] = (char *)malloc((len + 1) * sizeof(char));
556 if (env[0] == NULL) {
560 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
561 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
562 env[1] = (char *)malloc((len + 1) * sizeof(char));
563 if (env[1] == NULL) {
567 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
575 /* env variable ends by NULL element */
576 while (env && env[i]) {
583 context_res->env = env;
584 context_res->uid = uid;
585 context_res->gid = pwd.pw_gid;
590 static char **__generate_argv(const char *args)
592 /* Create args vector
593 * req_id + pkgid + args
595 * vector size = # of args +
596 *(req_id + pkgid + NULL termination = 3)
597 * Last value must be NULL for execv.
605 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
606 if (FALSE == ret_parse) {
607 ERR("Failed to split args: %s", args);
608 ERR("messsage: %s", gerr->message);
613 for (i = 0; i < argcp; i++)
614 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
619 void __set_environment(gpointer user_data)
621 user_ctx *ctx = (user_ctx *)user_data;
623 if (set_environement(ctx))
624 ERR("Failed to set env for the user : %d", ctx->uid);
627 static int __fork_and_exec_with_args(char **argv, uid_t uid)
629 user_ctx *user_context;
630 GError *error = NULL;
634 user_context = get_user_context(uid);
636 ERR("Failed to getenv");
640 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
641 __set_environment, (gpointer)user_context, &pid,
644 ERR("Failed to excute backend: %s", error->message);
646 free_user_context(user_context);
650 free_user_context(user_context);
655 static int __change_job_info(struct backend_job *job, uid_t uid,
660 pkgmgrinfo_appinfo_h handle = NULL;
661 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
662 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
663 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
664 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
665 job->req_type != REQUEST_TYPE_ENABLE_APP &&
666 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
667 return PMINFO_R_ERROR;
669 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
670 if (ret != PMINFO_R_OK)
671 return PMINFO_R_ERROR;
673 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
674 if (ret != PMINFO_R_OK)
677 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
679 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
681 ret = PMINFO_R_ERROR;
685 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
686 if (ret != PMINFO_R_OK)
690 job->appid = strdup(job->pkgid);
692 job->pkgid = strdup(pkgid);
695 pkgmgrinfo_appinfo_destroy_appinfo(handle);
700 static int __process_install(struct backend_job *job)
704 char args[MAX_PKG_ARGS_LEN];
709 backend_cmd = job->backend_path;
710 if (backend_cmd == NULL)
713 req_id = g_shell_quote(job->req_id);
714 pkgid = g_shell_quote(job->pkgid);
715 if (!req_id || !pkgid)
718 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
719 req_id, pkgid, (int)job->target_uid, job->args);
721 argv = __generate_argv(args);
723 pid = __fork_and_exec_with_args(argv, APPFW_UID);
731 static int __process_mount_install(struct backend_job *job)
735 char args[MAX_PKG_ARGS_LEN];
740 backend_cmd = job->backend_path;
741 if (backend_cmd == NULL)
744 req_id = g_shell_quote(job->req_id);
745 pkgid = g_shell_quote(job->pkgid);
746 if (!req_id || !pkgid)
749 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
750 req_id, pkgid, (int)job->target_uid, job->args);
752 argv = __generate_argv(args);
754 pid = __fork_and_exec_with_args(argv, APPFW_UID);
762 static int __process_reinstall(struct backend_job *job)
766 char args[MAX_PKG_ARGS_LEN];
771 backend_cmd = job->backend_path;
772 if (backend_cmd == NULL)
775 req_id = g_shell_quote(job->req_id);
776 pkgid = g_shell_quote(job->pkgid);
777 if (!req_id || !pkgid)
780 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
781 req_id, pkgid, (int)job->target_uid);
782 argv = __generate_argv(args);
784 pid = __fork_and_exec_with_args(argv, APPFW_UID);
793 static int __process_uninstall(struct backend_job *job)
797 char args[MAX_PKG_ARGS_LEN];
800 backend_cmd = job->backend_path;
801 if (backend_cmd == NULL)
804 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
805 job->req_id, job->pkgid, (int)job->target_uid);
806 argv = __generate_argv(args);
808 pid = __fork_and_exec_with_args(argv, APPFW_UID);
815 static int __process_move(struct backend_job *job)
819 char args[MAX_PKG_ARGS_LEN];
822 backend_cmd = job->backend_path;
823 if (backend_cmd == NULL)
826 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
827 job->req_id, job->pkgid, (int)job->target_uid, job->args);
828 argv = __generate_argv(args);
830 pid = __fork_and_exec_with_args(argv, APPFW_UID);
837 static int __process_enable_pkg(struct backend_job *job)
841 char args[MAX_PKG_ARGS_LEN];
842 pkgmgrinfo_pkginfo_h pkginfo_h;
848 backend_cmd = job->backend_path;
849 if (backend_cmd == NULL)
852 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
853 job->pkgid, job->target_uid, &pkginfo_h);
854 if (ret != PMINFO_R_OK) {
855 ERR("Failed to get appinfo");
859 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
860 if (ret != PMINFO_R_OK) {
861 ERR("Failed to get global value");
862 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
866 if ((is_global && job->target_uid != GLOBAL_USER) ||
867 (!is_global && job->target_uid == GLOBAL_USER)) {
868 ERR("Invalid attempt to enable pkg");
869 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
873 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
874 if (ret != PMINFO_R_OK) {
875 ERR("Failed to get readonly value");
876 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
880 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
881 backend_cmd, job->req_id, (int)job->target_uid,
882 job->pkgid, (is_readonly) ? "--preload" : "");
883 argv = __generate_argv(args);
884 pid = __fork_and_exec_with_args(argv, APPFW_UID);
887 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
892 static int __process_disable_pkg(struct backend_job *job)
896 char args[MAX_PKG_ARGS_LEN];
897 pkgmgrinfo_pkginfo_h pkginfo_h;
903 backend_cmd = job->backend_path;
904 if (backend_cmd == NULL)
907 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
908 job->pkgid, job->target_uid, &pkginfo_h);
909 if (ret != PMINFO_R_OK) {
910 ERR("Failed to get appinfo");
914 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
915 if (ret != PMINFO_R_OK) {
916 ERR("Failed to get global value");
917 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
921 if ((is_global && job->target_uid != GLOBAL_USER) ||
922 (!is_global && job->target_uid == GLOBAL_USER)) {
923 ERR("Invalid attempt to disable pkg");
924 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
928 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
929 if (ret != PMINFO_R_OK) {
930 ERR("Failed to get readonly value");
931 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
935 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
936 backend_cmd, job->req_id, (int)job->target_uid,
937 job->pkgid, (is_readonly) ? "--preload" : "");
938 argv = __generate_argv(args);
940 pid = __fork_and_exec_with_args(argv, APPFW_UID);
944 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
948 static int __process_register_pkg_update_info(struct backend_job *job)
952 if (!job->extra_data) {
953 _return_value_to_caller(job->req_id,
954 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
958 ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
959 (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
960 if (ret == PMINFO_R_OK)
961 _return_value_to_caller(job->req_id,
962 g_variant_new("(i)", PKGMGR_R_OK));
964 _return_value_to_caller(job->req_id,
965 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
967 pkgmgrinfo_updateinfo_destroy(job->extra_data);
968 job->extra_data = NULL;
973 static int __process_unregister_pkg_update_info(struct backend_job *job)
975 int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
976 (job->pkgid, job->target_uid);
978 if (ret == PMINFO_R_OK)
979 _return_value_to_caller(job->req_id,
980 g_variant_new("(i)", PKGMGR_R_OK));
982 _return_value_to_caller(job->req_id,
983 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
987 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
989 int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
992 if (ret != PMINFO_R_OK) {
993 _return_value_to_caller(job->req_id,
994 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
998 if (__is_admin_user(job->caller_uid)) {
999 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1001 if (ret != PMINFO_R_OK) {
1002 _return_value_to_caller(job->req_id,
1003 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1007 _return_value_to_caller(job->req_id,
1008 g_variant_new("(i)", PKGMGR_R_OK));
1013 static int __process_enable_app(struct backend_job *job)
1016 bool is_global = false;
1018 /* get actual pkgid and replace it to appid which is currently stored
1021 ret = __change_job_info(job, job->target_uid, &is_global);
1022 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1023 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1024 PKGMGR_INSTALLER_START_KEY_STR,
1025 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1027 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1028 PKGMGR_INSTALLER_END_KEY_STR,
1029 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1034 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1035 PKGMGR_INSTALLER_START_KEY_STR,
1036 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1038 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1039 job->target_uid, 0);
1040 if (ret != PMINFO_R_OK)
1041 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1042 PKGMGR_INSTALLER_END_KEY_STR,
1043 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1046 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1047 PKGMGR_INSTALLER_END_KEY_STR,
1048 PKGMGR_INSTALLER_OK_EVENT_STR,
1054 static int __process_disable_app(struct backend_job *job)
1057 bool is_global = false;
1059 /* get actual pkgid and replace it to appid which is currently stored
1062 ret = __change_job_info(job, job->target_uid, &is_global);
1063 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1064 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1065 PKGMGR_INSTALLER_START_KEY_STR,
1066 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1068 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1069 PKGMGR_INSTALLER_END_KEY_STR,
1070 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1075 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1076 PKGMGR_INSTALLER_START_KEY_STR,
1077 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1079 ret = __kill_app(job->appid, job->target_uid);
1081 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1082 PKGMGR_INSTALLER_END_KEY_STR,
1083 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1087 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1088 job->target_uid, 1);
1089 if (ret != PMINFO_R_OK)
1090 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1091 PKGMGR_INSTALLER_END_KEY_STR,
1092 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1095 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1096 PKGMGR_INSTALLER_END_KEY_STR,
1097 PKGMGR_INSTALLER_OK_EVENT_STR,
1103 static int __process_enable_global_app_for_uid(struct backend_job *job)
1106 bool is_global = true;
1108 /* get actual pkgid and replace it to appid which is currently stored
1111 ret = __change_job_info(job, job->target_uid, &is_global);
1112 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1113 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1114 PKGMGR_INSTALLER_START_KEY_STR,
1115 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1117 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1118 PKGMGR_INSTALLER_END_KEY_STR,
1119 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1124 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1125 PKGMGR_INSTALLER_START_KEY_STR,
1126 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1129 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1130 job->appid, job->target_uid, 0);
1131 if (ret != PMINFO_R_OK)
1132 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1133 PKGMGR_INSTALLER_END_KEY_STR,
1134 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1137 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1138 PKGMGR_INSTALLER_END_KEY_STR,
1139 PKGMGR_INSTALLER_OK_EVENT_STR,
1145 static int __process_disable_global_app_for_uid(struct backend_job *job)
1148 bool is_global = true;
1150 /* get actual pkgid and replace it to appid which is currently stored
1153 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1154 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1155 _send_app_signal(job->target_uid, job->req_id,
1156 job->pkgid, job->pkgid,
1157 PKGMGR_INSTALLER_START_KEY_STR,
1158 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1160 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1161 PKGMGR_INSTALLER_END_KEY_STR,
1162 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1167 _send_app_signal(job->target_uid, job->req_id,
1168 job->pkgid, job->appid,
1169 PKGMGR_INSTALLER_START_KEY_STR,
1170 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1173 ret = __kill_app(job->appid, job->target_uid);
1174 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1175 job->appid, job->target_uid, 1);
1177 if (ret != PMINFO_R_OK)
1178 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1179 PKGMGR_INSTALLER_END_KEY_STR,
1180 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1183 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1184 PKGMGR_INSTALLER_END_KEY_STR,
1185 PKGMGR_INSTALLER_OK_EVENT_STR,
1191 static int __process_getsize(struct backend_job *job)
1193 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1195 char args[MAX_PKG_ARGS_LEN];
1198 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1199 backend_cmd, job->pkgid, job->args, job->caller_uid,
1200 job->req_id, job->target_uid);
1201 argv = __generate_argv(args);
1202 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1209 static int __process_getsize_sync(struct backend_job *job)
1211 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1213 char args[MAX_PKG_ARGS_LEN];
1214 char fifo_path[PATH_MAX];
1215 struct getsize_sync_extra_info *extra_getsize_info;
1218 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1221 extra_getsize_info = calloc(1, sizeof(struct getsize_sync_extra_info));
1222 if (!extra_getsize_info) {
1223 ERR("memory alloc failed");
1227 extra_getsize_info->getsize_fifo = strdup(fifo_path);
1228 if (!extra_getsize_info->getsize_fifo) {
1229 ERR("out of memory");
1233 if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1234 ERR("failed to mkfifo");
1237 job->extra_data = extra_getsize_info;
1239 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1240 backend_cmd, job->pkgid, job->args, job->caller_uid,
1241 job->req_id, job->target_uid);
1242 argv = __generate_argv(args);
1243 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1248 ERR("failed to execute backend");
1251 if (__setup_size_info_io(job) < 0) {
1252 ERR("failed to setup io handler");
1259 _return_value_to_caller(job->req_id,
1260 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1264 static int __process_cleardata(struct backend_job *job)
1266 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1268 char args[MAX_PKG_ARGS_LEN];
1271 if ((int)job->target_uid < REGULAR_USER)
1274 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1275 backend_cmd, job->pkgid, job->target_uid);
1276 argv = __generate_argv(args);
1277 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1283 static int __process_clearcache(struct backend_job *job)
1285 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1287 char args[MAX_PKG_ARGS_LEN];
1290 if ((int)job->target_uid < REGULAR_USER)
1293 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1294 backend_cmd, job->pkgid, job->target_uid);
1295 argv = __generate_argv(args);
1296 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1302 static int __process_kill(struct backend_job *job)
1305 pkgmgrinfo_pkginfo_h handle;
1308 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1311 ERR("Failed to get handle");
1312 _return_value_to_caller(job->req_id,
1313 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1317 pdata = calloc(1, sizeof(pkgcmd_data));
1318 if (pdata == NULL) {
1319 ERR("memory alloc failed");
1320 _return_value_to_caller(job->req_id,
1321 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1324 pdata->cmd = strdup("kill");
1325 if (pdata->cmd == NULL) {
1326 ERR("out of memory");
1327 _return_value_to_caller(job->req_id,
1328 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1332 pdata->uid = job->target_uid;
1333 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1334 __pkgcmd_app_cb, pdata, job->target_uid);
1336 _return_value_to_caller(job->req_id,
1337 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1341 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1343 ERR("pkgmgrinfo_appinfo_get_list() failed");
1350 static int __process_check(struct backend_job *job)
1353 pkgmgrinfo_pkginfo_h handle;
1356 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1359 ERR("Failed to get handle");
1360 _return_value_to_caller(job->req_id,
1361 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1365 pdata = calloc(1, sizeof(pkgcmd_data));
1366 if (pdata == NULL) {
1367 ERR("memory alloc failed");
1368 _return_value_to_caller(job->req_id,
1369 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1372 pdata->cmd = strdup("check");
1373 if (pdata->cmd == NULL) {
1374 ERR("out of memory");
1375 _return_value_to_caller(job->req_id,
1376 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1380 pdata->uid = job->target_uid;
1381 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1382 __pkgcmd_app_cb, pdata, job->target_uid);
1384 _return_value_to_caller(job->req_id,
1385 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1389 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1391 ERR("pkgmgrinfo_appinfo_get_list() failed");
1398 static int __process_generate_license_request(struct backend_job *job)
1402 char req_data[MAX_PKG_ARGS_LEN];
1403 unsigned int req_data_len;
1404 char license_url[MAX_PKG_ARGS_LEN];
1405 unsigned int license_url_len;
1407 resp_data = job->args;
1408 req_data_len = sizeof(req_data);
1409 license_url_len = sizeof(license_url);
1411 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1412 req_data, &req_data_len, license_url, &license_url_len);
1413 if (ret != TADC_SUCCESS) {
1414 ERR("drm_tizen_generate_license_request failed: %d", ret);
1415 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1416 PKGMGR_R_ESYSTEM, "", ""));
1417 is_drm_busy = false;
1421 _return_value_to_caller(job->req_id,
1422 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1428 static int __process_register_license(struct backend_job *job)
1433 resp_data = job->args;
1435 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1436 if (ret != TADC_SUCCESS) {
1437 ERR("drm_tizen_register_license failed: %d", ret);
1438 _return_value_to_caller(job->req_id,
1439 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1440 is_drm_busy = false;
1444 _return_value_to_caller(job->req_id,
1445 g_variant_new("(i)", PKGMGR_R_OK));
1450 static int __process_decrypt_package(struct backend_job *job)
1453 char *drm_file_path;
1454 char *decrypted_file_path;
1456 drm_file_path = job->pkgid;
1457 decrypted_file_path = job->args;
1459 /* TODO: check ownership of decrypted file */
1460 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1461 decrypted_file_path, strlen(decrypted_file_path));
1462 if (ret != TADC_SUCCESS) {
1463 ERR("drm_tizen_register_license failed: %d", ret);
1464 _return_value_to_caller(job->req_id,
1465 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1466 is_drm_busy = false;
1470 _return_value_to_caller(job->req_id,
1471 g_variant_new("(i)", PKGMGR_R_OK));
1472 is_drm_busy = false;
1477 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1480 bool is_global = false;
1483 ret = __change_job_info(job, job->target_uid, &is_global);
1484 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1487 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1488 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1489 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1490 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1493 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1495 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1496 job->appid, job->target_uid, flag);
1497 if (ret != PMINFO_R_OK)
1498 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1499 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1500 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1503 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1504 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1505 PKGMGR_INSTALLER_OK_EVENT_STR,
1511 static int __process_set_restriction_mode(struct backend_job *job)
1516 mode = atoi(job->args);
1517 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1519 _return_value_to_caller(job->req_id,
1520 g_variant_new("(i)", ret));
1525 static int __process_unset_restriction_mode(struct backend_job *job)
1530 mode = atoi(job->args);
1531 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1533 _return_value_to_caller(job->req_id,
1534 g_variant_new("(i)", ret));
1539 static int __process_get_restriction_mode(struct backend_job *job)
1544 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1546 _return_value_to_caller(job->req_id,
1547 g_variant_new("(ii)", mode, ret));
1552 static int __process_set_app_label(struct backend_job *job)
1556 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1557 job->target_uid, job->args);
1558 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1563 static int __process_migrate_external_image(struct backend_job *job)
1567 char args[MAX_PKG_ARGS_LEN];
1570 backend_cmd = job->backend_path;
1571 if (backend_cmd == NULL)
1574 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1575 backend_cmd, job->req_id, job->pkgid,
1576 (int)job->target_uid, job->args);
1578 argv = __generate_argv(args);
1580 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1586 static int __post_process(int ret, int x, struct backend_job *job)
1589 __set_backend_free(x);
1590 _free_backend_job(job);
1592 g_hash_table_insert(backend_info_table, (gpointer)ret,
1598 gboolean queue_job(void *data)
1600 struct backend_job *job = NULL;
1604 /* Pop a job from queue */
1605 for (x = 0; x < num_of_backends; x++) {
1606 if (__is_backend_busy(x))
1609 job = _pop_queue(x);
1614 /* all backend messages queue are empty or busy */
1615 if (x == num_of_backends || job == NULL) {
1616 DBG("no job available");
1620 /* set current backend job */
1621 DBG("handle request type [%d]", job->req_type);
1623 #ifdef TIZEN_FEATURE_CSR
1624 if (job->req_type == REQUEST_TYPE_INSTALL ||
1625 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1626 job->req_type == REQUEST_TYPE_REINSTALL) {
1627 ret = __check_csr(job->pkgid);
1630 _send_fail_signal(job);
1631 _free_backend_job(job);
1637 switch (job->req_type) {
1638 case REQUEST_TYPE_INSTALL:
1639 __set_backend_busy(x);
1641 ret = __process_install(job);
1642 __post_process(ret, x, job);
1644 case REQUEST_TYPE_MOUNT_INSTALL:
1645 __set_backend_busy(x);
1647 ret = __process_mount_install(job);
1648 __post_process(ret, x, job);
1650 case REQUEST_TYPE_REINSTALL:
1651 __set_backend_busy(x);
1653 ret = __process_reinstall(job);
1654 __post_process(ret, x, job);
1656 case REQUEST_TYPE_UNINSTALL:
1657 __set_backend_busy(x);
1659 ret = __process_uninstall(job);
1660 __post_process(ret, x, job);
1662 case REQUEST_TYPE_MOVE:
1663 __set_backend_busy(x);
1665 ret = __process_move(job);
1666 __post_process(ret, x, job);
1668 case REQUEST_TYPE_ENABLE_PKG:
1669 __set_backend_busy(x);
1671 ret = __process_enable_pkg(job);
1673 _send_fail_signal(job);
1674 __post_process(ret, x, job);
1676 case REQUEST_TYPE_DISABLE_PKG:
1677 __set_backend_busy(x);
1679 ret = __process_disable_pkg(job);
1681 _send_fail_signal(job);
1682 __post_process(ret, x, job);
1684 case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1685 ret = __process_register_pkg_update_info(job);
1686 __free_extra_info(job);
1687 _free_backend_job(job);
1689 case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1690 ret = __process_unregister_pkg_update_info(job);
1691 _free_backend_job(job);
1693 case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1694 ret = __process_unregister_all_pkg_update_info(job);
1695 _free_backend_job(job);
1697 case REQUEST_TYPE_ENABLE_APP:
1698 ret = __process_enable_app(job);
1699 _free_backend_job(job);
1701 case REQUEST_TYPE_DISABLE_APP:
1702 ret = __process_disable_app(job);
1703 _free_backend_job(job);
1705 case REQUEST_TYPE_GETSIZE:
1706 __set_backend_busy(x);
1707 ret = __process_getsize(job);
1708 __post_process(ret, x, job);
1710 case REQUEST_TYPE_GETSIZE_SYNC:
1711 __set_backend_busy(x);
1712 ret = __process_getsize_sync(job);
1714 __free_extra_info(job);
1715 __post_process(ret, x, job);
1717 case REQUEST_TYPE_CLEARDATA:
1718 __set_backend_busy(x);
1720 ret = __process_cleardata(job);
1721 __post_process(ret, x, job);
1723 case REQUEST_TYPE_CLEARCACHE:
1724 __set_backend_busy(x);
1726 ret = __process_clearcache(job);
1727 __post_process(ret, x, job);
1729 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1730 ret = __process_enable_global_app_for_uid(job);
1731 _free_backend_job(job);
1733 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1734 ret = __process_disable_global_app_for_uid(job);
1735 _free_backend_job(job);
1737 case REQUEST_TYPE_KILL:
1738 ret = __process_kill(job);
1739 _free_backend_job(job);
1741 case REQUEST_TYPE_CHECK:
1742 ret = __process_check(job);
1743 _free_backend_job(job);
1745 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1746 ret = __process_generate_license_request(job);
1747 _free_backend_job(job);
1749 case REQUEST_TYPE_REGISTER_LICENSE:
1750 ret = __process_register_license(job);
1751 _free_backend_job(job);
1753 case REQUEST_TYPE_DECRYPT_PACKAGE:
1754 ret = __process_decrypt_package(job);
1755 _free_backend_job(job);
1757 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1758 ret = __process_update_app_splash_screen(job, 1);
1759 _free_backend_job(job);
1761 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1762 ret = __process_update_app_splash_screen(job, 0);
1763 _free_backend_job(job);
1765 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1766 ret = __process_set_restriction_mode(job);
1767 _free_backend_job(job);
1769 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1770 ret = __process_unset_restriction_mode(job);
1771 _free_backend_job(job);
1773 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1774 ret = __process_get_restriction_mode(job);
1775 _free_backend_job(job);
1777 case REQUEST_TYPE_SET_APP_LABEL:
1778 ret = __process_set_app_label(job);
1779 _free_backend_job(job);
1781 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1782 __set_backend_busy(x);
1784 ret = __process_migrate_external_image(job);
1785 __post_process(ret, x, job);
1795 int main(int argc, char *argv[])
1799 DBG("server start");
1801 if (__register_signal_handler()) {
1802 ERR("failed to register signal handler");
1806 r = _init_backend_queue();
1808 ERR("Queue Initialization Failed");
1812 r = __init_backend_info();
1814 ERR("backend info init failed");
1818 r = _init_request_handler();
1820 ERR("dbus init failed");
1824 #if !GLIB_CHECK_VERSION(2, 35, 0)
1827 mainloop = g_main_loop_new(NULL, FALSE);
1829 ERR("g_main_loop_new failed");
1833 DBG("Main loop is created.");
1835 g_main_loop_run(mainloop);
1837 DBG("Quit main loop.");
1838 _fini_request_handler();
1839 __fini_backend_info();
1840 _fini_backend_queue();
1842 g_source_remove(swid);
1843 g_io_channel_unref(sio);
1845 DBG("package manager server terminated.");