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;
86 static GIOChannel *sio;
88 static GHashTable *backend_info_table;
89 static GMainLoop *mainloop;
91 static int __check_backend_status_for_exit(void);
92 static int __check_queue_status_for_exit(void);
93 static int __is_backend_busy(int position);
94 static void __set_backend_busy(int position);
95 static void __set_backend_free(int position);
97 gboolean exit_server(void *data);
99 /* To check whether a particular backend is free/busy */
100 static int __is_backend_busy(int position)
102 return backend_busy & (1 << position);
104 /* To set a particular backend as busy */
105 static void __set_backend_busy(int position)
107 backend_busy = backend_busy | (1 << position);
109 /* To set a particular backend as free */
110 static void __set_backend_free(int position)
112 backend_busy = backend_busy & ~(1 << position);
115 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
121 char buf[MAX_LONGLONG_LENGTH];
122 long long result = 0;
123 struct backend_job *job = (struct backend_job *)data;
125 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
126 if (s != G_IO_STATUS_NORMAL) {
127 ERR("getsize fd read failed: %s", err->message);
131 if (strlen(buf) == 0) {
139 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
140 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
142 unlink(job->extra->getsize_fifo);
143 free(job->extra->getsize_fifo);
144 job->extra->getsize_fifo = NULL;
149 static int __setup_size_info_io(struct backend_job *job)
153 job->extra->getsize_fd = open(job->extra->getsize_fifo,
154 O_RDONLY | O_NONBLOCK);
155 if (job->extra->getsize_fd < 0) {
156 ERR("failed to open the fifo(%s), errno(%d)",
157 job->extra->getsize_fifo, errno);
161 job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
162 if (!job->extra->getsize_io)
164 g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
165 g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
166 getsize_wid = g_io_add_watch(job->extra->getsize_io,
167 G_IO_IN, getsize_io_handler, job);
169 ERR("failed to add io watch");
176 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
182 struct signalfd_siginfo fdsi;
183 struct backend_job *job;
187 s = g_io_channel_read_chars(io, (gchar *)&fdsi,
188 sizeof(struct signalfd_siginfo), &len, &err);
189 if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
190 ERR("Signal read failed");
195 pid = waitpid(-1, &status, WNOHANG);
196 job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
199 ERR("Unknown child exit");
203 __set_backend_free(job->backend_slot);
204 if (WIFSIGNALED(status)) {
205 _send_fail_signal(job);
206 INFO("backend[%s][%d] exit with signal[%d]", job->backend_type,
207 pid, WTERMSIG(status));
208 } else if (WEXITSTATUS(status)) {
209 INFO("backend[%s][%d] exit with error", job->backend_type, pid);
211 INFO("backend[%s][%d] exit", job->backend_type, pid);
215 if (job->extra->getsize_fifo) {
216 ERR("invalid backend close");
217 _return_value_to_caller(job->req_id,
218 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
222 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
223 g_idle_add(queue_job, NULL);
228 static int __init_backend_info(void)
230 backend_info_table = g_hash_table_new_full(g_direct_hash,
231 g_direct_equal, NULL,
232 (GDestroyNotify)_free_backend_job);
237 static void __fini_backend_info(void)
239 /*Free backend info */
240 g_hash_table_destroy(backend_info_table);
243 static int __register_signal_handler(void)
249 sigaddset(&mask, SIGCHLD);
251 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
252 ERR("sigprocmask failed");
256 sfd = signalfd(-1, &mask, SFD_NONBLOCK);
258 ERR("signalfd failed");
262 sio = g_io_channel_unix_new(sfd);
263 g_io_channel_set_close_on_unref(sio, TRUE);
264 g_io_channel_set_encoding(sio, NULL, NULL);
265 g_io_channel_set_buffered(sio, FALSE);
266 swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
268 g_timeout_add_seconds(2, exit_server, NULL);
273 static int __check_backend_status_for_exit(void)
276 for (i = 0; i < num_of_backends; i++) {
277 if (__is_backend_busy(i))
283 static int __check_queue_status_for_exit(void)
286 for (i = 0; i < num_of_backends; i++) {
287 if (_is_queue_empty(i) == 0)
293 gboolean exit_server(void *data)
295 DBG("exit_server Start");
296 if (__check_backend_status_for_exit() &&
297 __check_queue_status_for_exit()) {
298 g_main_loop_quit(mainloop);
304 #ifdef TIZEN_FEATURE_CSR
305 static int __check_csr(const char *path)
307 csr_cs_context_h context = NULL;
308 csr_cs_malware_h detected = NULL;
311 ret = csr_cs_context_create(&context);
312 if (ret != CSR_ERROR_NONE) {
313 ERR("Failed to create csr context");
318 ret = csr_cs_scan_file(context, path, &detected);
319 DBG("CSR result[%d]", ret);
321 csr_cs_context_destroy(context);
322 if (detected != NULL) {
323 ERR("CSR Denied[%s] Installation", path);
332 static int __kill_app(char *appid, uid_t uid)
338 is_running = aul_app_is_running_for_uid(appid, uid);
339 /* app is not running */
343 pid = aul_app_get_pid_for_uid(appid, uid);
347 ret = aul_terminate_pid_for_uid(pid, uid);
348 if (ret != AUL_R_OK) {
349 ERR("failed to terminate app(%d)", appid);
356 static int __check_app(char *appid, uid_t uid)
361 is_running = aul_app_is_running_for_uid(appid, uid);
365 pid = aul_app_get_pid_for_uid(appid, uid);
370 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
376 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
378 if (handle == NULL) {
379 perror("appinfo handle is NULL\n");
382 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
384 perror("Failed to get app exec path\n");
387 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
389 perror("Failed to get appid\n");
392 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
394 perror("Failed to get pkgid\n");
398 if (strcmp(pdata->cmd, "kill") == 0) {
399 pdata->pid = __check_app(appid, pdata->uid);
401 ret = __kill_app(appid, pdata->uid);
402 } else if (strcmp(pdata->cmd, "check") == 0) {
403 pdata->pid = __check_app(appid, pdata->uid);
409 void free_user_context(user_ctx *ctx)
416 /* env variable ends by NULL element */
426 int set_environement(user_ctx *ctx)
437 if (ctx->uid != APPFW_UID) {
438 if (setuid(ctx->uid)) {
439 ERR("setuid failed: %d", errno);
443 if (setgid(ctx->gid)) {
444 ERR("setgid failed: %d", errno);
449 n = getgroups(0, NULL);
451 ERR("Failed to get the number of supplementary group IDs");
455 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
456 if (groups == NULL) {
457 ERR("out of memory");
461 n = getgroups(n, groups);
463 ERR("Failed to get list of supplementary group IDs");
468 groups[n++] = EXT_STORAGE_GROUP;
469 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
470 groups[n++] = MEDIA_STORAGE_GROUP;
472 if (setgroups(n, groups) < 0) {
473 ERR("setgroups failed: %d", errno);
480 /* env variable ends by NULL element */
482 if (putenv(env[i]) != 0)
489 user_ctx *get_user_context(uid_t uid)
491 /* we can use getpwnam because this is used only after a
492 * fork and just before an execv
493 * No concurrencial call can corrupt the data
494 * returned by getpwuid
496 user_ctx *context_res;
498 char buf[1024] = {0, };
499 struct passwd pwd, *result;
504 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
505 if (ret != 0 || result == NULL)
509 context_res = (user_ctx *)malloc(sizeof(user_ctx));
514 env = (char **)malloc(3 * sizeof(char *));
519 /* Build environment context */
520 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
521 env[0] = (char *)malloc((len + 1) * sizeof(char));
522 if (env[0] == NULL) {
526 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
527 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
528 env[1] = (char *)malloc((len + 1) * sizeof(char));
529 if (env[1] == NULL) {
533 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
541 /* env variable ends by NULL element */
542 while (env && env[i]) {
549 context_res->env = env;
550 context_res->uid = uid;
551 context_res->gid = pwd.pw_gid;
556 static char **__generate_argv(const char *args)
558 /* Create args vector
559 * req_id + pkgid + args
561 * vector size = # of args +
562 *(req_id + pkgid + NULL termination = 3)
563 * Last value must be NULL for execv.
571 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
572 if (FALSE == ret_parse) {
573 ERR("Failed to split args: %s", args);
574 ERR("messsage: %s", gerr->message);
579 for (i = 0; i < argcp; i++)
580 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
585 void __set_environment(gpointer user_data)
587 user_ctx *ctx = (user_ctx *)user_data;
589 if (set_environement(ctx))
590 ERR("Failed to set env for the user : %d", ctx->uid);
593 static int __fork_and_exec_with_args(char **argv, uid_t uid)
595 user_ctx *user_context;
596 GError *error = NULL;
600 user_context = get_user_context(uid);
602 ERR("Failed to getenv");
606 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
607 __set_environment, (gpointer)user_context, &pid,
610 ERR("Failed to excute backend: %s", error->message);
612 free_user_context(user_context);
616 free_user_context(user_context);
621 static int __change_job_info(struct backend_job *job, uid_t uid,
626 pkgmgrinfo_appinfo_h handle = NULL;
627 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
628 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
629 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
630 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
631 job->req_type != REQUEST_TYPE_ENABLE_APP &&
632 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
633 return PMINFO_R_ERROR;
635 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
636 if (ret != PMINFO_R_OK)
637 return PMINFO_R_ERROR;
639 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
640 if (ret != PMINFO_R_OK)
643 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
645 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
647 ret = PMINFO_R_ERROR;
651 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
652 if (ret != PMINFO_R_OK)
656 job->appid = strdup(job->pkgid);
658 job->pkgid = strdup(pkgid);
661 pkgmgrinfo_appinfo_destroy_appinfo(handle);
666 static int __process_install(struct backend_job *job)
670 char args[MAX_PKG_ARGS_LEN];
675 backend_cmd = job->backend_path;
676 if (backend_cmd == NULL)
679 req_id = g_shell_quote(job->req_id);
680 pkgid = g_shell_quote(job->pkgid);
681 if (!req_id || !pkgid)
684 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
685 req_id, pkgid, (int)job->target_uid, job->args);
687 argv = __generate_argv(args);
689 pid = __fork_and_exec_with_args(argv, APPFW_UID);
697 static int __process_mount_install(struct backend_job *job)
701 char args[MAX_PKG_ARGS_LEN];
706 backend_cmd = job->backend_path;
707 if (backend_cmd == NULL)
710 req_id = g_shell_quote(job->req_id);
711 pkgid = g_shell_quote(job->pkgid);
712 if (!req_id || !pkgid)
715 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
716 req_id, pkgid, (int)job->target_uid, job->args);
718 argv = __generate_argv(args);
720 pid = __fork_and_exec_with_args(argv, APPFW_UID);
728 static int __process_reinstall(struct backend_job *job)
732 char args[MAX_PKG_ARGS_LEN];
737 backend_cmd = job->backend_path;
738 if (backend_cmd == NULL)
741 req_id = g_shell_quote(job->req_id);
742 pkgid = g_shell_quote(job->pkgid);
743 if (!req_id || !pkgid)
746 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
747 req_id, pkgid, (int)job->target_uid);
748 argv = __generate_argv(args);
750 pid = __fork_and_exec_with_args(argv, APPFW_UID);
759 static int __process_uninstall(struct backend_job *job)
763 char args[MAX_PKG_ARGS_LEN];
766 backend_cmd = job->backend_path;
767 if (backend_cmd == NULL)
770 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
771 job->req_id, job->pkgid, (int)job->target_uid);
772 argv = __generate_argv(args);
774 pid = __fork_and_exec_with_args(argv, APPFW_UID);
781 static int __process_move(struct backend_job *job)
785 char args[MAX_PKG_ARGS_LEN];
788 backend_cmd = job->backend_path;
789 if (backend_cmd == NULL)
792 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
793 job->req_id, job->pkgid, (int)job->target_uid, job->args);
794 argv = __generate_argv(args);
796 pid = __fork_and_exec_with_args(argv, APPFW_UID);
803 static int __process_enable_pkg(struct backend_job *job)
807 char args[MAX_PKG_ARGS_LEN];
808 pkgmgrinfo_pkginfo_h pkginfo_h;
814 backend_cmd = job->backend_path;
815 if (backend_cmd == NULL)
818 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
819 job->pkgid, job->target_uid, &pkginfo_h);
820 if (ret != PMINFO_R_OK) {
821 ERR("Failed to get appinfo");
825 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
826 if (ret != PMINFO_R_OK) {
827 ERR("Failed to get global value");
828 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
832 if ((is_global && job->target_uid != GLOBAL_USER) ||
833 (!is_global && job->target_uid == GLOBAL_USER)) {
834 ERR("Invalid attempt to enable pkg");
835 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
839 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
840 if (ret != PMINFO_R_OK) {
841 ERR("Failed to get readonly value");
842 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
846 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
847 backend_cmd, job->req_id, (int)job->target_uid,
848 job->pkgid, (is_readonly) ? "--preload" : "");
849 argv = __generate_argv(args);
850 pid = __fork_and_exec_with_args(argv, APPFW_UID);
853 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
858 static int __process_disable_pkg(struct backend_job *job)
862 char args[MAX_PKG_ARGS_LEN];
863 pkgmgrinfo_pkginfo_h pkginfo_h;
869 backend_cmd = job->backend_path;
870 if (backend_cmd == NULL)
873 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
874 job->pkgid, job->target_uid, &pkginfo_h);
875 if (ret != PMINFO_R_OK) {
876 ERR("Failed to get appinfo");
880 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
881 if (ret != PMINFO_R_OK) {
882 ERR("Failed to get global value");
883 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
887 if ((is_global && job->target_uid != GLOBAL_USER) ||
888 (!is_global && job->target_uid == GLOBAL_USER)) {
889 ERR("Invalid attempt to disable pkg");
890 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
894 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
895 if (ret != PMINFO_R_OK) {
896 ERR("Failed to get readonly value");
897 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
901 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
902 backend_cmd, job->req_id, (int)job->target_uid,
903 job->pkgid, (is_readonly) ? "--preload" : "");
904 argv = __generate_argv(args);
906 pid = __fork_and_exec_with_args(argv, APPFW_UID);
910 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
914 static int __process_enable_app(struct backend_job *job)
917 bool is_global = false;
919 /* get actual pkgid and replace it to appid which is currently stored
922 ret = __change_job_info(job, job->target_uid, &is_global);
923 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
924 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
925 PKGMGR_INSTALLER_START_KEY_STR,
926 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
928 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
929 PKGMGR_INSTALLER_END_KEY_STR,
930 PKGMGR_INSTALLER_FAIL_EVENT_STR,
935 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
936 PKGMGR_INSTALLER_START_KEY_STR,
937 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
939 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
941 if (ret != PMINFO_R_OK)
942 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
943 PKGMGR_INSTALLER_END_KEY_STR,
944 PKGMGR_INSTALLER_FAIL_EVENT_STR,
947 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
948 PKGMGR_INSTALLER_END_KEY_STR,
949 PKGMGR_INSTALLER_OK_EVENT_STR,
955 static int __process_disable_app(struct backend_job *job)
958 bool is_global = false;
960 /* get actual pkgid and replace it to appid which is currently stored
963 ret = __change_job_info(job, job->target_uid, &is_global);
964 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
965 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
966 PKGMGR_INSTALLER_START_KEY_STR,
967 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
969 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
970 PKGMGR_INSTALLER_END_KEY_STR,
971 PKGMGR_INSTALLER_FAIL_EVENT_STR,
976 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
977 PKGMGR_INSTALLER_START_KEY_STR,
978 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
980 ret = __kill_app(job->appid, job->target_uid);
982 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
983 PKGMGR_INSTALLER_END_KEY_STR,
984 PKGMGR_INSTALLER_FAIL_EVENT_STR,
988 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
990 if (ret != PMINFO_R_OK)
991 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
992 PKGMGR_INSTALLER_END_KEY_STR,
993 PKGMGR_INSTALLER_FAIL_EVENT_STR,
996 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
997 PKGMGR_INSTALLER_END_KEY_STR,
998 PKGMGR_INSTALLER_OK_EVENT_STR,
1004 static int __process_enable_global_app_for_uid(struct backend_job *job)
1007 bool is_global = true;
1009 /* get actual pkgid and replace it to appid which is currently stored
1012 ret = __change_job_info(job, job->target_uid, &is_global);
1013 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1014 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1015 PKGMGR_INSTALLER_START_KEY_STR,
1016 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1018 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1019 PKGMGR_INSTALLER_END_KEY_STR,
1020 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1025 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1026 PKGMGR_INSTALLER_START_KEY_STR,
1027 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1030 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1031 job->appid, job->target_uid, 0);
1032 if (ret != PMINFO_R_OK)
1033 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1034 PKGMGR_INSTALLER_END_KEY_STR,
1035 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1038 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1039 PKGMGR_INSTALLER_END_KEY_STR,
1040 PKGMGR_INSTALLER_OK_EVENT_STR,
1046 static int __process_disable_global_app_for_uid(struct backend_job *job)
1049 bool is_global = true;
1051 /* get actual pkgid and replace it to appid which is currently stored
1054 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1055 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1056 _send_app_signal(job->target_uid, job->req_id,
1057 job->pkgid, job->pkgid,
1058 PKGMGR_INSTALLER_START_KEY_STR,
1059 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1061 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1062 PKGMGR_INSTALLER_END_KEY_STR,
1063 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1068 _send_app_signal(job->target_uid, job->req_id,
1069 job->pkgid, job->appid,
1070 PKGMGR_INSTALLER_START_KEY_STR,
1071 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1074 ret = __kill_app(job->appid, job->target_uid);
1075 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1076 job->appid, job->target_uid, 1);
1078 if (ret != PMINFO_R_OK)
1079 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1080 PKGMGR_INSTALLER_END_KEY_STR,
1081 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1084 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1085 PKGMGR_INSTALLER_END_KEY_STR,
1086 PKGMGR_INSTALLER_OK_EVENT_STR,
1092 static int __process_getsize(struct backend_job *job)
1094 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1096 char args[MAX_PKG_ARGS_LEN];
1099 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1100 backend_cmd, job->pkgid, job->args, job->caller_uid,
1101 job->req_id, job->target_uid);
1102 argv = __generate_argv(args);
1103 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1110 static int __process_getsize_sync(struct backend_job *job)
1112 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1114 char args[MAX_PKG_ARGS_LEN];
1115 char fifo_path[PATH_MAX];
1118 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1121 job->extra = calloc(1, sizeof(struct job_extra_info));
1123 ERR("memory alloc failed");
1127 job->extra->getsize_fifo = strdup(fifo_path);
1128 if (!job->extra->getsize_fifo) {
1129 ERR("out of memory");
1133 if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1134 ERR("failed to mkfifo");
1138 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1139 backend_cmd, job->pkgid, job->args, job->caller_uid,
1140 job->req_id, job->target_uid);
1141 argv = __generate_argv(args);
1142 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1147 ERR("failed to execute backend");
1150 if (__setup_size_info_io(job) < 0) {
1151 ERR("failed to setup io handler");
1158 _return_value_to_caller(job->req_id,
1159 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1163 static int __process_cleardata(struct backend_job *job)
1165 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1167 char args[MAX_PKG_ARGS_LEN];
1170 if ((int)job->target_uid < REGULAR_USER)
1173 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1174 backend_cmd, job->pkgid, job->target_uid);
1175 argv = __generate_argv(args);
1176 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1182 static int __process_clearcache(struct backend_job *job)
1184 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1186 char args[MAX_PKG_ARGS_LEN];
1189 if ((int)job->target_uid < REGULAR_USER)
1192 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1193 backend_cmd, job->pkgid, job->target_uid);
1194 argv = __generate_argv(args);
1195 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1201 static int __process_kill(struct backend_job *job)
1204 pkgmgrinfo_pkginfo_h handle;
1207 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1210 ERR("Failed to get handle");
1211 _return_value_to_caller(job->req_id,
1212 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1216 pdata = calloc(1, sizeof(pkgcmd_data));
1217 if (pdata == NULL) {
1218 ERR("memory alloc failed");
1219 _return_value_to_caller(job->req_id,
1220 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1223 pdata->cmd = strdup("kill");
1224 if (pdata->cmd == NULL) {
1225 ERR("out of memory");
1226 _return_value_to_caller(job->req_id,
1227 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1231 pdata->uid = job->target_uid;
1232 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1233 __pkgcmd_app_cb, pdata, job->target_uid);
1235 _return_value_to_caller(job->req_id,
1236 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1240 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1242 ERR("pkgmgrinfo_appinfo_get_list() failed");
1249 static int __process_check(struct backend_job *job)
1252 pkgmgrinfo_pkginfo_h handle;
1255 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1258 ERR("Failed to get handle");
1259 _return_value_to_caller(job->req_id,
1260 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1264 pdata = calloc(1, sizeof(pkgcmd_data));
1265 if (pdata == NULL) {
1266 ERR("memory alloc failed");
1267 _return_value_to_caller(job->req_id,
1268 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1271 pdata->cmd = strdup("check");
1272 if (pdata->cmd == NULL) {
1273 ERR("out of memory");
1274 _return_value_to_caller(job->req_id,
1275 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1279 pdata->uid = job->target_uid;
1280 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1281 __pkgcmd_app_cb, pdata, job->target_uid);
1283 _return_value_to_caller(job->req_id,
1284 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1288 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1290 ERR("pkgmgrinfo_appinfo_get_list() failed");
1297 static int __process_generate_license_request(struct backend_job *job)
1301 char req_data[MAX_PKG_ARGS_LEN];
1302 unsigned int req_data_len;
1303 char license_url[MAX_PKG_ARGS_LEN];
1304 unsigned int license_url_len;
1306 resp_data = job->args;
1307 req_data_len = sizeof(req_data);
1308 license_url_len = sizeof(license_url);
1310 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1311 req_data, &req_data_len, license_url, &license_url_len);
1312 if (ret != TADC_SUCCESS) {
1313 ERR("drm_tizen_generate_license_request failed: %d", ret);
1314 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1315 PKGMGR_R_ESYSTEM, "", ""));
1319 _return_value_to_caller(job->req_id,
1320 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1326 static int __process_register_license(struct backend_job *job)
1331 resp_data = job->args;
1333 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1334 if (ret != TADC_SUCCESS) {
1335 ERR("drm_tizen_register_license failed: %d", ret);
1336 _return_value_to_caller(job->req_id,
1337 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1341 _return_value_to_caller(job->req_id,
1342 g_variant_new("(i)", PKGMGR_R_OK));
1347 static int __process_decrypt_package(struct backend_job *job)
1350 char *drm_file_path;
1351 char *decrypted_file_path;
1353 drm_file_path = job->pkgid;
1354 decrypted_file_path = job->args;
1356 /* TODO: check ownership of decrypted file */
1357 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1358 decrypted_file_path, strlen(decrypted_file_path));
1359 if (ret != TADC_SUCCESS) {
1360 ERR("drm_tizen_register_license failed: %d", ret);
1361 _return_value_to_caller(job->req_id,
1362 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1366 _return_value_to_caller(job->req_id,
1367 g_variant_new("(i)", PKGMGR_R_OK));
1372 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1375 bool is_global = false;
1378 ret = __change_job_info(job, job->target_uid, &is_global);
1379 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1382 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1383 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1384 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1385 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1388 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1390 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1391 job->appid, job->target_uid, flag);
1392 if (ret != PMINFO_R_OK)
1393 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1394 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1395 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1398 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1399 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1400 PKGMGR_INSTALLER_OK_EVENT_STR,
1406 static int __process_set_restriction_mode(struct backend_job *job)
1411 mode = atoi(job->args);
1412 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1414 _return_value_to_caller(job->req_id,
1415 g_variant_new("(i)", ret));
1420 static int __process_unset_restriction_mode(struct backend_job *job)
1425 mode = atoi(job->args);
1426 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1428 _return_value_to_caller(job->req_id,
1429 g_variant_new("(i)", ret));
1434 static int __process_get_restriction_mode(struct backend_job *job)
1439 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1441 _return_value_to_caller(job->req_id,
1442 g_variant_new("(ii)", mode, ret));
1447 static int __process_set_app_label(struct backend_job *job)
1451 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1452 job->target_uid, job->args);
1453 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1458 static int __process_migrate_external_image(struct backend_job *job)
1462 char args[MAX_PKG_ARGS_LEN];
1465 backend_cmd = job->backend_path;
1466 if (backend_cmd == NULL)
1469 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1470 backend_cmd, job->req_id, job->pkgid,
1471 (int)job->target_uid, job->args);
1473 argv = __generate_argv(args);
1475 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1481 static int __post_process(int ret, int x, struct backend_job *job)
1484 __set_backend_free(x);
1485 _free_backend_job(job);
1487 g_hash_table_insert(backend_info_table, (gpointer)ret,
1493 gboolean queue_job(void *data)
1495 struct backend_job *job = NULL;
1499 /* Pop a job from queue */
1500 for (x = 0; x < num_of_backends; x++) {
1501 if (__is_backend_busy(x))
1504 job = _pop_queue(x);
1509 /* all backend messages queue are empty or busy */
1510 if (x == num_of_backends || job == NULL) {
1511 DBG("no job available");
1515 /* set current backend job */
1516 DBG("handle request type [%d]", job->req_type);
1518 #ifdef TIZEN_FEATURE_CSR
1519 if (job->req_type == REQUEST_TYPE_INSTALL ||
1520 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1521 job->req_type == REQUEST_TYPE_REINSTALL) {
1522 ret = __check_csr(job->pkgid);
1525 _send_fail_signal(job);
1526 _free_backend_job(job);
1532 switch (job->req_type) {
1533 case REQUEST_TYPE_INSTALL:
1534 __set_backend_busy(x);
1535 ret = __process_install(job);
1536 __post_process(ret, x, job);
1538 case REQUEST_TYPE_MOUNT_INSTALL:
1539 __set_backend_busy(x);
1540 ret = __process_mount_install(job);
1541 __post_process(ret, x, job);
1543 case REQUEST_TYPE_REINSTALL:
1544 __set_backend_busy(x);
1545 ret = __process_reinstall(job);
1546 __post_process(ret, x, job);
1548 case REQUEST_TYPE_UNINSTALL:
1549 __set_backend_busy(x);
1550 ret = __process_uninstall(job);
1551 __post_process(ret, x, job);
1553 case REQUEST_TYPE_MOVE:
1554 __set_backend_busy(x);
1555 ret = __process_move(job);
1556 __post_process(ret, x, job);
1558 case REQUEST_TYPE_ENABLE_PKG:
1559 __set_backend_busy(x);
1560 ret = __process_enable_pkg(job);
1562 _send_fail_signal(job);
1563 __post_process(ret, x, job);
1565 case REQUEST_TYPE_DISABLE_PKG:
1566 __set_backend_busy(x);
1567 ret = __process_disable_pkg(job);
1569 _send_fail_signal(job);
1570 __post_process(ret, x, job);
1572 case REQUEST_TYPE_ENABLE_APP:
1573 ret = __process_enable_app(job);
1574 _free_backend_job(job);
1576 case REQUEST_TYPE_DISABLE_APP:
1577 ret = __process_disable_app(job);
1578 _free_backend_job(job);
1580 case REQUEST_TYPE_GETSIZE:
1581 __set_backend_busy(x);
1582 ret = __process_getsize(job);
1583 __post_process(ret, x, job);
1585 case REQUEST_TYPE_GETSIZE_SYNC:
1586 __set_backend_busy(x);
1587 ret = __process_getsize_sync(job);
1589 __free_extra_info(job);
1590 __post_process(ret, x, job);
1592 case REQUEST_TYPE_CLEARDATA:
1593 __set_backend_busy(x);
1594 ret = __process_cleardata(job);
1595 __post_process(ret, x, job);
1597 case REQUEST_TYPE_CLEARCACHE:
1598 __set_backend_busy(x);
1599 ret = __process_clearcache(job);
1600 __post_process(ret, x, job);
1602 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1603 ret = __process_enable_global_app_for_uid(job);
1604 _free_backend_job(job);
1606 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1607 ret = __process_disable_global_app_for_uid(job);
1608 _free_backend_job(job);
1610 case REQUEST_TYPE_KILL:
1611 ret = __process_kill(job);
1612 _free_backend_job(job);
1614 case REQUEST_TYPE_CHECK:
1615 ret = __process_check(job);
1616 _free_backend_job(job);
1618 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1619 ret = __process_generate_license_request(job);
1620 _free_backend_job(job);
1622 case REQUEST_TYPE_REGISTER_LICENSE:
1623 ret = __process_register_license(job);
1624 _free_backend_job(job);
1626 case REQUEST_TYPE_DECRYPT_PACKAGE:
1627 ret = __process_decrypt_package(job);
1628 _free_backend_job(job);
1630 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1631 ret = __process_update_app_splash_screen(job, 1);
1632 _free_backend_job(job);
1634 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1635 ret = __process_update_app_splash_screen(job, 0);
1636 _free_backend_job(job);
1638 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1639 ret = __process_set_restriction_mode(job);
1640 _free_backend_job(job);
1642 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1643 ret = __process_unset_restriction_mode(job);
1644 _free_backend_job(job);
1646 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1647 ret = __process_get_restriction_mode(job);
1648 _free_backend_job(job);
1650 case REQUEST_TYPE_SET_APP_LABEL:
1651 ret = __process_set_app_label(job);
1652 _free_backend_job(job);
1654 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1655 __set_backend_busy(x);
1656 ret = __process_migrate_external_image(job);
1657 __post_process(ret, x, job);
1667 int main(int argc, char *argv[])
1671 DBG("server start");
1673 if (__register_signal_handler()) {
1674 ERR("failed to register signal handler");
1678 r = _init_backend_queue();
1680 ERR("Queue Initialization Failed");
1684 r = __init_backend_info();
1686 ERR("backend info init failed");
1690 r = _init_request_handler();
1692 ERR("dbus init failed");
1696 #if !GLIB_CHECK_VERSION(2, 35, 0)
1699 mainloop = g_main_loop_new(NULL, FALSE);
1701 ERR("g_main_loop_new failed");
1705 DBG("Main loop is created.");
1707 g_main_loop_run(mainloop);
1709 DBG("Quit main loop.");
1710 _fini_request_handler();
1711 __fini_backend_info();
1712 _fini_backend_queue();
1714 g_source_remove(swid);
1715 g_io_channel_unref(sio);
1717 DBG("package manager server terminated.");