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 #ifdef TIZEN_FEATURE_CSR
47 #include <csr-content-screening.h>
50 #include "pkgmgr_installer.h"
51 #include "pkgmgr-server.h"
53 #include "package-manager.h"
56 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
60 #define EXT_STORAGE_GROUP 10001
61 #define EXT_STORAGE_APPDATA_GROUP 10002
62 #define MEDIA_STORAGE_GROUP 10502
63 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
64 #define MAX_LONGLONG_LENGTH 32
79 8 bit value to represent maximum 8 backends.
80 Each bit position corresponds to a queue slot which
81 is dynamically determined.
83 static char backend_busy = 0;
84 extern int num_of_backends;
85 bool is_drm_busy = false;
87 static GIOChannel *sio;
89 static GHashTable *backend_info_table;
90 static GMainLoop *mainloop;
92 static int __check_backend_status_for_exit(void);
93 static int __check_queue_status_for_exit(void);
94 static int __is_backend_busy(int position);
95 static void __set_backend_busy(int position);
96 static void __set_backend_free(int position);
98 gboolean exit_server(void *data);
100 /* To check whether a particular backend is free/busy */
101 static int __is_backend_busy(int position)
103 return backend_busy & (1 << position);
105 /* To set a particular backend as busy */
106 static void __set_backend_busy(int position)
108 backend_busy = backend_busy | (1 << position);
110 /* To set a particular backend as free */
111 static void __set_backend_free(int position)
113 backend_busy = backend_busy & ~(1 << position);
116 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
122 char buf[MAX_LONGLONG_LENGTH];
123 long long result = 0;
124 struct backend_job *job = (struct backend_job *)data;
126 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
127 if (s != G_IO_STATUS_NORMAL) {
128 ERR("getsize fd read failed: %s", err->message);
132 if (strlen(buf) == 0) {
140 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
141 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
143 unlink(job->extra->getsize_fifo);
144 free(job->extra->getsize_fifo);
145 job->extra->getsize_fifo = NULL;
150 static int __setup_size_info_io(struct backend_job *job)
154 job->extra->getsize_fd = open(job->extra->getsize_fifo,
155 O_RDONLY | O_NONBLOCK);
156 if (job->extra->getsize_fd < 0) {
157 ERR("failed to open the fifo(%s), errno(%d)",
158 job->extra->getsize_fifo, errno);
162 job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
163 if (!job->extra->getsize_io)
165 g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
166 g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
167 getsize_wid = g_io_add_watch(job->extra->getsize_io,
168 G_IO_IN, getsize_io_handler, job);
170 ERR("failed to add io watch");
177 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
183 struct signalfd_siginfo fdsi;
184 struct backend_job *job;
188 s = g_io_channel_read_chars(io, (gchar *)&fdsi,
189 sizeof(struct signalfd_siginfo), &len, &err);
190 if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
191 ERR("Signal read failed");
196 pid = waitpid(-1, &status, WNOHANG);
197 job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
200 ERR("Unknown child exit");
204 __set_backend_free(job->backend_slot);
205 if (WIFSIGNALED(status)) {
206 _send_fail_signal(job);
207 INFO("backend[%s][%d] exit with signal[%d]", job->backend_type,
208 pid, WTERMSIG(status));
209 } else if (WEXITSTATUS(status)) {
210 INFO("backend[%s][%d] exit with error", job->backend_type, pid);
212 INFO("backend[%s][%d] exit", job->backend_type, pid);
216 if (job->extra->getsize_fifo) {
217 ERR("invalid backend close");
218 _return_value_to_caller(job->req_id,
219 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
223 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
224 g_idle_add(queue_job, NULL);
229 static int __init_backend_info(void)
231 backend_info_table = g_hash_table_new_full(g_direct_hash,
232 g_direct_equal, NULL,
233 (GDestroyNotify)_free_backend_job);
238 static void __fini_backend_info(void)
240 /*Free backend info */
241 g_hash_table_destroy(backend_info_table);
244 static int __register_signal_handler(void)
250 sigaddset(&mask, SIGCHLD);
252 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
253 ERR("sigprocmask failed");
257 sfd = signalfd(-1, &mask, SFD_NONBLOCK);
259 ERR("signalfd failed");
263 sio = g_io_channel_unix_new(sfd);
264 g_io_channel_set_close_on_unref(sio, TRUE);
265 g_io_channel_set_encoding(sio, NULL, NULL);
266 g_io_channel_set_buffered(sio, FALSE);
267 swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
269 g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, exit_server, NULL, NULL);
274 static int __check_backend_status_for_exit(void)
277 for (i = 0; i < num_of_backends; i++) {
278 if (__is_backend_busy(i))
284 static int __check_queue_status_for_exit(void)
287 for (i = 0; i < num_of_backends; i++) {
288 if (_is_queue_empty(i) == 0)
294 gboolean exit_server(void *data)
296 DBG("exit_server Start");
297 if (__check_backend_status_for_exit() &&
298 __check_queue_status_for_exit() && !is_drm_busy) {
299 g_main_loop_quit(mainloop);
305 #ifdef TIZEN_FEATURE_CSR
306 static int __check_csr(const char *path)
308 csr_cs_context_h context = NULL;
309 csr_cs_malware_h detected = NULL;
312 ret = csr_cs_context_create(&context);
313 if (ret != CSR_ERROR_NONE) {
314 ERR("Failed to create csr context");
319 ret = csr_cs_scan_file(context, path, &detected);
320 DBG("CSR result[%d]", ret);
322 csr_cs_context_destroy(context);
323 if (detected != NULL) {
324 ERR("CSR Denied[%s] Installation", path);
333 static int __kill_app(char *appid, uid_t uid)
339 is_running = aul_app_is_running_for_uid(appid, uid);
340 /* app is not running */
344 pid = aul_app_get_pid_for_uid(appid, uid);
348 ret = aul_terminate_pid_for_uid(pid, uid);
349 if (ret != AUL_R_OK) {
350 ERR("failed to terminate app(%d)", appid);
357 static int __check_app(char *appid, uid_t uid)
362 is_running = aul_app_is_running_for_uid(appid, uid);
366 pid = aul_app_get_pid_for_uid(appid, uid);
371 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
377 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
379 if (handle == NULL) {
380 perror("appinfo handle is NULL\n");
383 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
385 perror("Failed to get app exec path\n");
388 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
390 perror("Failed to get appid\n");
393 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
395 perror("Failed to get pkgid\n");
399 if (strcmp(pdata->cmd, "kill") == 0) {
400 pdata->pid = __check_app(appid, pdata->uid);
402 ret = __kill_app(appid, pdata->uid);
403 } else if (strcmp(pdata->cmd, "check") == 0) {
404 pdata->pid = __check_app(appid, pdata->uid);
410 void free_user_context(user_ctx *ctx)
417 /* env variable ends by NULL element */
427 int set_environement(user_ctx *ctx)
438 if (ctx->uid != APPFW_UID) {
439 if (setuid(ctx->uid)) {
440 ERR("setuid failed: %d", errno);
444 if (setgid(ctx->gid)) {
445 ERR("setgid failed: %d", errno);
450 n = getgroups(0, NULL);
452 ERR("Failed to get the number of supplementary group IDs");
456 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
457 if (groups == NULL) {
458 ERR("out of memory");
462 n = getgroups(n, groups);
464 ERR("Failed to get list of supplementary group IDs");
469 groups[n++] = EXT_STORAGE_GROUP;
470 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
471 groups[n++] = MEDIA_STORAGE_GROUP;
473 if (setgroups(n, groups) < 0) {
474 ERR("setgroups failed: %d", errno);
481 /* env variable ends by NULL element */
483 if (putenv(env[i]) != 0)
490 user_ctx *get_user_context(uid_t uid)
492 /* we can use getpwnam because this is used only after a
493 * fork and just before an execv
494 * No concurrencial call can corrupt the data
495 * returned by getpwuid
497 user_ctx *context_res;
499 char buf[1024] = {0, };
500 struct passwd pwd, *result;
505 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
506 if (ret != 0 || result == NULL)
510 context_res = (user_ctx *)malloc(sizeof(user_ctx));
515 env = (char **)malloc(3 * sizeof(char *));
520 /* Build environment context */
521 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
522 env[0] = (char *)malloc((len + 1) * sizeof(char));
523 if (env[0] == NULL) {
527 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
528 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
529 env[1] = (char *)malloc((len + 1) * sizeof(char));
530 if (env[1] == NULL) {
534 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
542 /* env variable ends by NULL element */
543 while (env && env[i]) {
550 context_res->env = env;
551 context_res->uid = uid;
552 context_res->gid = pwd.pw_gid;
557 static char **__generate_argv(const char *args)
559 /* Create args vector
560 * req_id + pkgid + args
562 * vector size = # of args +
563 *(req_id + pkgid + NULL termination = 3)
564 * Last value must be NULL for execv.
572 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
573 if (FALSE == ret_parse) {
574 ERR("Failed to split args: %s", args);
575 ERR("messsage: %s", gerr->message);
580 for (i = 0; i < argcp; i++)
581 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
586 void __set_environment(gpointer user_data)
588 user_ctx *ctx = (user_ctx *)user_data;
590 if (set_environement(ctx))
591 ERR("Failed to set env for the user : %d", ctx->uid);
594 static int __fork_and_exec_with_args(char **argv, uid_t uid)
596 user_ctx *user_context;
597 GError *error = NULL;
601 user_context = get_user_context(uid);
603 ERR("Failed to getenv");
607 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
608 __set_environment, (gpointer)user_context, &pid,
611 ERR("Failed to excute backend: %s", error->message);
613 free_user_context(user_context);
617 free_user_context(user_context);
622 static int __change_job_info(struct backend_job *job, uid_t uid,
627 pkgmgrinfo_appinfo_h handle = NULL;
628 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
629 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
630 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
631 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
632 job->req_type != REQUEST_TYPE_ENABLE_APP &&
633 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
634 return PMINFO_R_ERROR;
636 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
637 if (ret != PMINFO_R_OK)
638 return PMINFO_R_ERROR;
640 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
641 if (ret != PMINFO_R_OK)
644 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
646 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
648 ret = PMINFO_R_ERROR;
652 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
653 if (ret != PMINFO_R_OK)
657 job->appid = strdup(job->pkgid);
659 job->pkgid = strdup(pkgid);
662 pkgmgrinfo_appinfo_destroy_appinfo(handle);
667 static int __process_install(struct backend_job *job)
671 char args[MAX_PKG_ARGS_LEN];
676 backend_cmd = job->backend_path;
677 if (backend_cmd == NULL)
680 req_id = g_shell_quote(job->req_id);
681 pkgid = g_shell_quote(job->pkgid);
682 if (!req_id || !pkgid)
685 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
686 req_id, pkgid, (int)job->target_uid, job->args);
688 argv = __generate_argv(args);
690 pid = __fork_and_exec_with_args(argv, APPFW_UID);
698 static int __process_mount_install(struct backend_job *job)
702 char args[MAX_PKG_ARGS_LEN];
707 backend_cmd = job->backend_path;
708 if (backend_cmd == NULL)
711 req_id = g_shell_quote(job->req_id);
712 pkgid = g_shell_quote(job->pkgid);
713 if (!req_id || !pkgid)
716 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
717 req_id, pkgid, (int)job->target_uid, job->args);
719 argv = __generate_argv(args);
721 pid = __fork_and_exec_with_args(argv, APPFW_UID);
729 static int __process_reinstall(struct backend_job *job)
733 char args[MAX_PKG_ARGS_LEN];
738 backend_cmd = job->backend_path;
739 if (backend_cmd == NULL)
742 req_id = g_shell_quote(job->req_id);
743 pkgid = g_shell_quote(job->pkgid);
744 if (!req_id || !pkgid)
747 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
748 req_id, pkgid, (int)job->target_uid);
749 argv = __generate_argv(args);
751 pid = __fork_and_exec_with_args(argv, APPFW_UID);
760 static int __process_uninstall(struct backend_job *job)
764 char args[MAX_PKG_ARGS_LEN];
767 backend_cmd = job->backend_path;
768 if (backend_cmd == NULL)
771 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
772 job->req_id, job->pkgid, (int)job->target_uid);
773 argv = __generate_argv(args);
775 pid = __fork_and_exec_with_args(argv, APPFW_UID);
782 static int __process_move(struct backend_job *job)
786 char args[MAX_PKG_ARGS_LEN];
789 backend_cmd = job->backend_path;
790 if (backend_cmd == NULL)
793 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
794 job->req_id, job->pkgid, (int)job->target_uid, job->args);
795 argv = __generate_argv(args);
797 pid = __fork_and_exec_with_args(argv, APPFW_UID);
804 static int __process_enable_pkg(struct backend_job *job)
808 char args[MAX_PKG_ARGS_LEN];
809 pkgmgrinfo_pkginfo_h pkginfo_h;
815 backend_cmd = job->backend_path;
816 if (backend_cmd == NULL)
819 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
820 job->pkgid, job->target_uid, &pkginfo_h);
821 if (ret != PMINFO_R_OK) {
822 ERR("Failed to get appinfo");
826 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
827 if (ret != PMINFO_R_OK) {
828 ERR("Failed to get global value");
829 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
833 if ((is_global && job->target_uid != GLOBAL_USER) ||
834 (!is_global && job->target_uid == GLOBAL_USER)) {
835 ERR("Invalid attempt to enable pkg");
836 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
840 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
841 if (ret != PMINFO_R_OK) {
842 ERR("Failed to get readonly value");
843 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
847 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
848 backend_cmd, job->req_id, (int)job->target_uid,
849 job->pkgid, (is_readonly) ? "--preload" : "");
850 argv = __generate_argv(args);
851 pid = __fork_and_exec_with_args(argv, APPFW_UID);
854 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
859 static int __process_disable_pkg(struct backend_job *job)
863 char args[MAX_PKG_ARGS_LEN];
864 pkgmgrinfo_pkginfo_h pkginfo_h;
870 backend_cmd = job->backend_path;
871 if (backend_cmd == NULL)
874 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
875 job->pkgid, job->target_uid, &pkginfo_h);
876 if (ret != PMINFO_R_OK) {
877 ERR("Failed to get appinfo");
881 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
882 if (ret != PMINFO_R_OK) {
883 ERR("Failed to get global value");
884 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
888 if ((is_global && job->target_uid != GLOBAL_USER) ||
889 (!is_global && job->target_uid == GLOBAL_USER)) {
890 ERR("Invalid attempt to disable pkg");
891 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
895 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
896 if (ret != PMINFO_R_OK) {
897 ERR("Failed to get readonly value");
898 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
902 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
903 backend_cmd, job->req_id, (int)job->target_uid,
904 job->pkgid, (is_readonly) ? "--preload" : "");
905 argv = __generate_argv(args);
907 pid = __fork_and_exec_with_args(argv, APPFW_UID);
911 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
915 static int __process_register_pkg_update_info(struct backend_job *job)
919 if (!job->extra_data) {
920 _return_value_to_caller(job->req_id,
921 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
925 ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
926 (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
927 if (ret == PMINFO_R_OK)
928 _return_value_to_caller(job->req_id,
929 g_variant_new("(i)", PKGMGR_R_OK));
931 _return_value_to_caller(job->req_id,
932 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
934 pkgmgrinfo_updateinfo_destroy(job->extra_data);
935 job->extra_data = NULL;
940 static int __process_unregister_pkg_update_info(struct backend_job *job)
942 int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
943 (job->pkgid, job->target_uid);
945 if (ret == PMINFO_R_OK)
946 _return_value_to_caller(job->req_id,
947 g_variant_new("(i)", PKGMGR_R_OK));
949 _return_value_to_caller(job->req_id,
950 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
954 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
956 int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
959 if (ret != PMINFO_R_OK) {
960 _return_value_to_caller(job->req_id,
961 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
965 if (__is_admin_user(job->caller_uid)) {
966 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
968 if (ret != PMINFO_R_OK) {
969 _return_value_to_caller(job->req_id,
970 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
974 _return_value_to_caller(job->req_id,
975 g_variant_new("(i)", PKGMGR_R_OK));
980 static int __process_enable_app(struct backend_job *job)
983 bool is_global = false;
985 /* get actual pkgid and replace it to appid which is currently stored
988 ret = __change_job_info(job, job->target_uid, &is_global);
989 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
990 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
991 PKGMGR_INSTALLER_START_KEY_STR,
992 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
994 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
995 PKGMGR_INSTALLER_END_KEY_STR,
996 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1001 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1002 PKGMGR_INSTALLER_START_KEY_STR,
1003 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1005 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1006 job->target_uid, 0);
1007 if (ret != PMINFO_R_OK)
1008 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1009 PKGMGR_INSTALLER_END_KEY_STR,
1010 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1013 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1014 PKGMGR_INSTALLER_END_KEY_STR,
1015 PKGMGR_INSTALLER_OK_EVENT_STR,
1021 static int __process_disable_app(struct backend_job *job)
1024 bool is_global = false;
1026 /* get actual pkgid and replace it to appid which is currently stored
1029 ret = __change_job_info(job, job->target_uid, &is_global);
1030 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1031 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1032 PKGMGR_INSTALLER_START_KEY_STR,
1033 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1035 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1036 PKGMGR_INSTALLER_END_KEY_STR,
1037 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1042 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1043 PKGMGR_INSTALLER_START_KEY_STR,
1044 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1046 ret = __kill_app(job->appid, job->target_uid);
1048 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1049 PKGMGR_INSTALLER_END_KEY_STR,
1050 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1054 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1055 job->target_uid, 1);
1056 if (ret != PMINFO_R_OK)
1057 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1058 PKGMGR_INSTALLER_END_KEY_STR,
1059 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1062 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1063 PKGMGR_INSTALLER_END_KEY_STR,
1064 PKGMGR_INSTALLER_OK_EVENT_STR,
1070 static int __process_enable_global_app_for_uid(struct backend_job *job)
1073 bool is_global = true;
1075 /* get actual pkgid and replace it to appid which is currently stored
1078 ret = __change_job_info(job, job->target_uid, &is_global);
1079 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1080 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1081 PKGMGR_INSTALLER_START_KEY_STR,
1082 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1084 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1085 PKGMGR_INSTALLER_END_KEY_STR,
1086 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1091 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1092 PKGMGR_INSTALLER_START_KEY_STR,
1093 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1096 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1097 job->appid, job->target_uid, 0);
1098 if (ret != PMINFO_R_OK)
1099 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1100 PKGMGR_INSTALLER_END_KEY_STR,
1101 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1104 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1105 PKGMGR_INSTALLER_END_KEY_STR,
1106 PKGMGR_INSTALLER_OK_EVENT_STR,
1112 static int __process_disable_global_app_for_uid(struct backend_job *job)
1115 bool is_global = true;
1117 /* get actual pkgid and replace it to appid which is currently stored
1120 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1121 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1122 _send_app_signal(job->target_uid, job->req_id,
1123 job->pkgid, job->pkgid,
1124 PKGMGR_INSTALLER_START_KEY_STR,
1125 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1127 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1128 PKGMGR_INSTALLER_END_KEY_STR,
1129 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1134 _send_app_signal(job->target_uid, job->req_id,
1135 job->pkgid, job->appid,
1136 PKGMGR_INSTALLER_START_KEY_STR,
1137 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1140 ret = __kill_app(job->appid, job->target_uid);
1141 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1142 job->appid, job->target_uid, 1);
1144 if (ret != PMINFO_R_OK)
1145 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1146 PKGMGR_INSTALLER_END_KEY_STR,
1147 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1150 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1151 PKGMGR_INSTALLER_END_KEY_STR,
1152 PKGMGR_INSTALLER_OK_EVENT_STR,
1158 static int __process_getsize(struct backend_job *job)
1160 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1162 char args[MAX_PKG_ARGS_LEN];
1165 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1166 backend_cmd, job->pkgid, job->args, job->caller_uid,
1167 job->req_id, job->target_uid);
1168 argv = __generate_argv(args);
1169 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1176 static int __process_getsize_sync(struct backend_job *job)
1178 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1180 char args[MAX_PKG_ARGS_LEN];
1181 char fifo_path[PATH_MAX];
1184 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1187 job->extra = calloc(1, sizeof(struct job_extra_info));
1189 ERR("memory alloc failed");
1193 job->extra->getsize_fifo = strdup(fifo_path);
1194 if (!job->extra->getsize_fifo) {
1195 ERR("out of memory");
1199 if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1200 ERR("failed to mkfifo");
1204 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1205 backend_cmd, job->pkgid, job->args, job->caller_uid,
1206 job->req_id, job->target_uid);
1207 argv = __generate_argv(args);
1208 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1213 ERR("failed to execute backend");
1216 if (__setup_size_info_io(job) < 0) {
1217 ERR("failed to setup io handler");
1224 _return_value_to_caller(job->req_id,
1225 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1229 static int __process_cleardata(struct backend_job *job)
1231 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1233 char args[MAX_PKG_ARGS_LEN];
1236 if ((int)job->target_uid < REGULAR_USER)
1239 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1240 backend_cmd, job->pkgid, job->target_uid);
1241 argv = __generate_argv(args);
1242 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1248 static int __process_clearcache(struct backend_job *job)
1250 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1252 char args[MAX_PKG_ARGS_LEN];
1255 if ((int)job->target_uid < REGULAR_USER)
1258 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1259 backend_cmd, job->pkgid, job->target_uid);
1260 argv = __generate_argv(args);
1261 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1267 static int __process_kill(struct backend_job *job)
1270 pkgmgrinfo_pkginfo_h handle;
1273 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1276 ERR("Failed to get handle");
1277 _return_value_to_caller(job->req_id,
1278 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1282 pdata = calloc(1, sizeof(pkgcmd_data));
1283 if (pdata == NULL) {
1284 ERR("memory alloc failed");
1285 _return_value_to_caller(job->req_id,
1286 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1289 pdata->cmd = strdup("kill");
1290 if (pdata->cmd == NULL) {
1291 ERR("out of memory");
1292 _return_value_to_caller(job->req_id,
1293 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1297 pdata->uid = job->target_uid;
1298 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1299 __pkgcmd_app_cb, pdata, job->target_uid);
1301 _return_value_to_caller(job->req_id,
1302 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1306 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1308 ERR("pkgmgrinfo_appinfo_get_list() failed");
1315 static int __process_check(struct backend_job *job)
1318 pkgmgrinfo_pkginfo_h handle;
1321 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1324 ERR("Failed to get handle");
1325 _return_value_to_caller(job->req_id,
1326 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1330 pdata = calloc(1, sizeof(pkgcmd_data));
1331 if (pdata == NULL) {
1332 ERR("memory alloc failed");
1333 _return_value_to_caller(job->req_id,
1334 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1337 pdata->cmd = strdup("check");
1338 if (pdata->cmd == NULL) {
1339 ERR("out of memory");
1340 _return_value_to_caller(job->req_id,
1341 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1345 pdata->uid = job->target_uid;
1346 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1347 __pkgcmd_app_cb, pdata, job->target_uid);
1349 _return_value_to_caller(job->req_id,
1350 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1354 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1356 ERR("pkgmgrinfo_appinfo_get_list() failed");
1363 static int __process_generate_license_request(struct backend_job *job)
1367 char req_data[MAX_PKG_ARGS_LEN];
1368 unsigned int req_data_len;
1369 char license_url[MAX_PKG_ARGS_LEN];
1370 unsigned int license_url_len;
1372 resp_data = job->args;
1373 req_data_len = sizeof(req_data);
1374 license_url_len = sizeof(license_url);
1376 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1377 req_data, &req_data_len, license_url, &license_url_len);
1378 if (ret != TADC_SUCCESS) {
1379 ERR("drm_tizen_generate_license_request failed: %d", ret);
1380 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1381 PKGMGR_R_ESYSTEM, "", ""));
1382 is_drm_busy = false;
1386 _return_value_to_caller(job->req_id,
1387 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1393 static int __process_register_license(struct backend_job *job)
1398 resp_data = job->args;
1400 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1401 if (ret != TADC_SUCCESS) {
1402 ERR("drm_tizen_register_license failed: %d", ret);
1403 _return_value_to_caller(job->req_id,
1404 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1405 is_drm_busy = false;
1409 _return_value_to_caller(job->req_id,
1410 g_variant_new("(i)", PKGMGR_R_OK));
1415 static int __process_decrypt_package(struct backend_job *job)
1418 char *drm_file_path;
1419 char *decrypted_file_path;
1421 drm_file_path = job->pkgid;
1422 decrypted_file_path = job->args;
1424 /* TODO: check ownership of decrypted file */
1425 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1426 decrypted_file_path, strlen(decrypted_file_path));
1427 if (ret != TADC_SUCCESS) {
1428 ERR("drm_tizen_register_license failed: %d", ret);
1429 _return_value_to_caller(job->req_id,
1430 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1431 is_drm_busy = false;
1435 _return_value_to_caller(job->req_id,
1436 g_variant_new("(i)", PKGMGR_R_OK));
1437 is_drm_busy = false;
1442 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1445 bool is_global = false;
1448 ret = __change_job_info(job, job->target_uid, &is_global);
1449 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1452 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1453 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1454 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1455 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1458 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1460 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1461 job->appid, job->target_uid, flag);
1462 if (ret != PMINFO_R_OK)
1463 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1464 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1465 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1468 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1469 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1470 PKGMGR_INSTALLER_OK_EVENT_STR,
1476 static int __process_set_restriction_mode(struct backend_job *job)
1481 mode = atoi(job->args);
1482 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1484 _return_value_to_caller(job->req_id,
1485 g_variant_new("(i)", ret));
1490 static int __process_unset_restriction_mode(struct backend_job *job)
1495 mode = atoi(job->args);
1496 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1498 _return_value_to_caller(job->req_id,
1499 g_variant_new("(i)", ret));
1504 static int __process_get_restriction_mode(struct backend_job *job)
1509 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1511 _return_value_to_caller(job->req_id,
1512 g_variant_new("(ii)", mode, ret));
1517 static int __process_set_app_label(struct backend_job *job)
1521 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1522 job->target_uid, job->args);
1523 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1528 static int __process_migrate_external_image(struct backend_job *job)
1532 char args[MAX_PKG_ARGS_LEN];
1535 backend_cmd = job->backend_path;
1536 if (backend_cmd == NULL)
1539 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1540 backend_cmd, job->req_id, job->pkgid,
1541 (int)job->target_uid, job->args);
1543 argv = __generate_argv(args);
1545 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1551 static int __post_process(int ret, int x, struct backend_job *job)
1554 __set_backend_free(x);
1555 _free_backend_job(job);
1557 g_hash_table_insert(backend_info_table, (gpointer)ret,
1563 gboolean queue_job(void *data)
1565 struct backend_job *job = NULL;
1569 /* Pop a job from queue */
1570 for (x = 0; x < num_of_backends; x++) {
1571 if (__is_backend_busy(x))
1574 job = _pop_queue(x);
1579 /* all backend messages queue are empty or busy */
1580 if (x == num_of_backends || job == NULL) {
1581 DBG("no job available");
1585 /* set current backend job */
1586 DBG("handle request type [%d]", job->req_type);
1588 #ifdef TIZEN_FEATURE_CSR
1589 if (job->req_type == REQUEST_TYPE_INSTALL ||
1590 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1591 job->req_type == REQUEST_TYPE_REINSTALL) {
1592 ret = __check_csr(job->pkgid);
1595 _send_fail_signal(job);
1596 _free_backend_job(job);
1602 switch (job->req_type) {
1603 case REQUEST_TYPE_INSTALL:
1604 __set_backend_busy(x);
1605 ret = __process_install(job);
1606 __post_process(ret, x, job);
1608 case REQUEST_TYPE_MOUNT_INSTALL:
1609 __set_backend_busy(x);
1610 ret = __process_mount_install(job);
1611 __post_process(ret, x, job);
1613 case REQUEST_TYPE_REINSTALL:
1614 __set_backend_busy(x);
1615 ret = __process_reinstall(job);
1616 __post_process(ret, x, job);
1618 case REQUEST_TYPE_UNINSTALL:
1619 __set_backend_busy(x);
1620 ret = __process_uninstall(job);
1621 __post_process(ret, x, job);
1623 case REQUEST_TYPE_MOVE:
1624 __set_backend_busy(x);
1625 ret = __process_move(job);
1626 __post_process(ret, x, job);
1628 case REQUEST_TYPE_ENABLE_PKG:
1629 __set_backend_busy(x);
1630 ret = __process_enable_pkg(job);
1632 _send_fail_signal(job);
1633 __post_process(ret, x, job);
1635 case REQUEST_TYPE_DISABLE_PKG:
1636 __set_backend_busy(x);
1637 ret = __process_disable_pkg(job);
1639 _send_fail_signal(job);
1640 __post_process(ret, x, job);
1642 case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1643 ret = __process_register_pkg_update_info(job);
1644 _free_backend_job(job);
1646 case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1647 ret = __process_unregister_pkg_update_info(job);
1648 _free_backend_job(job);
1650 case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1651 ret = __process_unregister_all_pkg_update_info(job);
1652 _free_backend_job(job);
1654 case REQUEST_TYPE_ENABLE_APP:
1655 ret = __process_enable_app(job);
1656 _free_backend_job(job);
1658 case REQUEST_TYPE_DISABLE_APP:
1659 ret = __process_disable_app(job);
1660 _free_backend_job(job);
1662 case REQUEST_TYPE_GETSIZE:
1663 __set_backend_busy(x);
1664 ret = __process_getsize(job);
1665 __post_process(ret, x, job);
1667 case REQUEST_TYPE_GETSIZE_SYNC:
1668 __set_backend_busy(x);
1669 ret = __process_getsize_sync(job);
1671 __free_extra_info(job);
1672 __post_process(ret, x, job);
1674 case REQUEST_TYPE_CLEARDATA:
1675 __set_backend_busy(x);
1676 ret = __process_cleardata(job);
1677 __post_process(ret, x, job);
1679 case REQUEST_TYPE_CLEARCACHE:
1680 __set_backend_busy(x);
1681 ret = __process_clearcache(job);
1682 __post_process(ret, x, job);
1684 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1685 ret = __process_enable_global_app_for_uid(job);
1686 _free_backend_job(job);
1688 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1689 ret = __process_disable_global_app_for_uid(job);
1690 _free_backend_job(job);
1692 case REQUEST_TYPE_KILL:
1693 ret = __process_kill(job);
1694 _free_backend_job(job);
1696 case REQUEST_TYPE_CHECK:
1697 ret = __process_check(job);
1698 _free_backend_job(job);
1700 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1701 ret = __process_generate_license_request(job);
1702 _free_backend_job(job);
1704 case REQUEST_TYPE_REGISTER_LICENSE:
1705 ret = __process_register_license(job);
1706 _free_backend_job(job);
1708 case REQUEST_TYPE_DECRYPT_PACKAGE:
1709 ret = __process_decrypt_package(job);
1710 _free_backend_job(job);
1712 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1713 ret = __process_update_app_splash_screen(job, 1);
1714 _free_backend_job(job);
1716 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1717 ret = __process_update_app_splash_screen(job, 0);
1718 _free_backend_job(job);
1720 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1721 ret = __process_set_restriction_mode(job);
1722 _free_backend_job(job);
1724 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1725 ret = __process_unset_restriction_mode(job);
1726 _free_backend_job(job);
1728 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1729 ret = __process_get_restriction_mode(job);
1730 _free_backend_job(job);
1732 case REQUEST_TYPE_SET_APP_LABEL:
1733 ret = __process_set_app_label(job);
1734 _free_backend_job(job);
1736 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1737 __set_backend_busy(x);
1738 ret = __process_migrate_external_image(job);
1739 __post_process(ret, x, job);
1749 int main(int argc, char *argv[])
1753 DBG("server start");
1755 if (__register_signal_handler()) {
1756 ERR("failed to register signal handler");
1760 r = _init_backend_queue();
1762 ERR("Queue Initialization Failed");
1766 r = __init_backend_info();
1768 ERR("backend info init failed");
1772 r = _init_request_handler();
1774 ERR("dbus init failed");
1778 #if !GLIB_CHECK_VERSION(2, 35, 0)
1781 mainloop = g_main_loop_new(NULL, FALSE);
1783 ERR("g_main_loop_new failed");
1787 DBG("Main loop is created.");
1789 g_main_loop_run(mainloop);
1791 DBG("Quit main loop.");
1792 _fini_request_handler();
1793 __fini_backend_info();
1794 _fini_backend_queue();
1796 g_source_remove(swid);
1797 g_io_channel_unref(sio);
1799 DBG("package manager server terminated.");