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>
40 #include <pkgmgr-info.h>
41 #include <pkgmgr/pkgmgr_parser_db.h>
42 #include <tzplatform_config.h>
43 #include <drm-tizen-apps.h>
44 #ifdef TIZEN_FEATURE_CSR
45 #include <csr-content-screening.h>
48 #include "pkgmgr_installer.h"
49 #include "pkgmgr-server.h"
51 #include "package-manager.h"
54 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
58 #define EXT_STORAGE_GROUP 10001
59 #define EXT_STORAGE_APPDATA_GROUP 10002
60 #define MEDIA_STORAGE_GROUP 10502
61 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
76 8 bit value to represent maximum 8 backends.
77 Each bit position corresponds to a queue slot which
78 is dynamically determined.
80 static char backend_busy = 0;
81 extern int num_of_backends;
83 struct signal_info_t {
88 static int pipe_sig[2];
89 static GIOChannel *pipe_io;
90 static guint pipe_wid;
91 static GHashTable *backend_info_table;
92 static GMainLoop *mainloop = NULL;
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);
99 static void sighandler(int signo);
101 gboolean exit_server(void *data);
103 /* To check whether a particular backend is free/busy */
104 static int __is_backend_busy(int position)
106 return backend_busy & (1 << position);
108 /* To set a particular backend as busy */
109 static void __set_backend_busy(int position)
111 backend_busy = backend_busy | (1 << position);
113 /* To set a particular backend as free */
114 static void __set_backend_free(int position)
116 backend_busy = backend_busy & ~(1 << position);
119 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond,
125 struct signal_info_t info;
126 struct backend_job *job;
128 s = g_io_channel_read_chars(io, (gchar *)&info,
129 sizeof(struct signal_info_t), &len, &err);
130 if (s != G_IO_STATUS_NORMAL) {
131 ERR("Signal pipe read failed: %s", err->message);
136 job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
137 (gconstpointer)info.pid);
139 ERR("Unknown child exit");
143 __set_backend_free(job->backend_slot);
144 if (WIFSIGNALED(info.status)) {
145 _send_fail_signal(job);
146 DBG("backend[%s] exit with signal[%d]", job->backend_type,
147 WTERMSIG(info.status));
148 } else if (WEXITSTATUS(info.status)) {
149 DBG("backend[%s] exit with error", job->backend_type);
151 DBG("backend[%s] exit", job->backend_type);
154 g_hash_table_remove(backend_info_table, (gconstpointer)info.pid);
155 g_idle_add(queue_job, NULL);
160 static int __init_backend_info(void)
162 backend_info_table = g_hash_table_new_full(g_direct_hash,
163 g_direct_equal, NULL,
164 (GDestroyNotify)_free_backend_job);
166 if (pipe(pipe_sig)) {
167 ERR("create pipe failed");
171 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
172 g_io_channel_set_encoding(pipe_io, NULL, NULL);
173 g_io_channel_set_buffered(pipe_io, FALSE);
174 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
179 static void __fini_backend_info(void)
181 g_source_remove(pipe_wid);
182 g_io_channel_unref(pipe_io);
186 /*Free backend info */
187 g_hash_table_destroy(backend_info_table);
190 static void sighandler(int signo)
192 struct signal_info_t info;
193 char buf[1024] = {0, };
195 info.pid = waitpid(-1, &info.status, WNOHANG);
196 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
197 ERR("failed to write result: %s",
198 strerror_r(errno, buf, sizeof(buf)));
201 static int __register_signal_handler(void)
203 static int sig_reg = 0;
204 struct sigaction act;
209 act.sa_handler = sighandler;
210 sigemptyset(&act.sa_mask);
211 act.sa_flags = SA_NOCLDSTOP;
212 if (sigaction(SIGCHLD, &act, NULL) < 0) {
213 ERR("signal: SIGCHLD failed");
217 g_timeout_add_seconds(2, exit_server, NULL);
223 static int __check_backend_status_for_exit(void)
226 for (i = 0; i < num_of_backends; i++) {
227 if (__is_backend_busy(i))
233 static int __check_queue_status_for_exit(void)
236 for (i = 0; i < num_of_backends; i++) {
237 if (_is_queue_empty(i) == 0)
243 gboolean exit_server(void *data)
245 DBG("exit_server Start");
246 if (__check_backend_status_for_exit() &&
247 __check_queue_status_for_exit()) {
248 g_main_loop_quit(mainloop);
254 #ifdef TIZEN_FEATURE_CSR
255 static int __check_csr(const char *path)
257 csr_cs_context_h context = NULL;
258 csr_cs_malware_h detected = NULL;
261 ret = csr_cs_context_create(&context);
262 if (ret != CSR_ERROR_NONE) {
263 ERR("Failed to create csr context");
268 ret = csr_cs_scan_file(context, path, &detected);
269 DBG("CSR result[%d]", ret);
271 csr_cs_context_destroy(context);
272 if (detected != NULL) {
273 ERR("CSR Denied[%s] Installation", path);
282 static int __kill_app(char *appid, uid_t uid)
288 is_running = aul_app_is_running_for_uid(appid, uid);
289 /* app is not running */
293 pid = aul_app_get_pid_for_uid(appid, uid);
297 ret = aul_terminate_pid_for_uid(pid, uid);
298 if (ret != AUL_R_OK) {
299 ERR("failed to terminate app(%d)", appid);
306 static int __check_app(char *appid, uid_t uid)
311 is_running = aul_app_is_running_for_uid(appid, uid);
315 pid = aul_app_get_pid_for_uid(appid, uid);
320 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
326 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
328 if (handle == NULL) {
329 perror("appinfo handle is NULL\n");
332 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
334 perror("Failed to get app exec path\n");
337 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
339 perror("Failed to get appid\n");
342 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
344 perror("Failed to get pkgid\n");
348 if (strcmp(pdata->cmd, "kill") == 0) {
349 pdata->pid = __check_app(appid, pdata->uid);
351 ret = __kill_app(appid, pdata->uid);
352 } else if (strcmp(pdata->cmd, "check") == 0) {
353 pdata->pid = __check_app(appid, pdata->uid);
359 void free_user_context(user_ctx* ctx)
366 /* env variable ends by NULL element */
376 int set_environement(user_ctx *ctx)
387 if (ctx->uid != APPFW_UID) {
388 if (setuid(ctx->uid)) {
389 ERR("setuid failed: %d", errno);
393 if (setgid(ctx->gid)) {
394 ERR("setgid failed: %d", errno);
399 n = getgroups(0, NULL);
401 ERR("Failed to get the number of supplementary group IDs");
405 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
406 if (groups == NULL) {
407 ERR("out of memory");
411 n = getgroups(n, groups);
413 ERR("Failed to get list of supplementary group IDs");
418 groups[n++] = EXT_STORAGE_GROUP;
419 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
420 groups[n++] = MEDIA_STORAGE_GROUP;
422 if (setgroups(n, groups) < 0) {
423 ERR("setgroups failed: %d", errno);
430 /* env variable ends by NULL element */
432 if (putenv(env[i]) != 0)
439 user_ctx *get_user_context(uid_t uid)
441 /* we can use getpwnam because this is used only after a
442 * fork and just before an execv
443 * No concurrencial call can corrupt the data
444 * returned by getpwuid
446 user_ctx *context_res;
448 char buf[1024] = {0, };
449 struct passwd pwd, *result;
454 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
455 if (ret != 0 || result == NULL)
459 context_res = (user_ctx *)malloc(sizeof(user_ctx));
464 env = (char **)malloc(3 * sizeof(char *));
469 /* Build environment context */
470 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
471 env[0] = (char *)malloc((len + 1) * sizeof(char));
472 if (env[0] == NULL) {
476 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
477 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
478 env[1] = (char *)malloc((len + 1) * sizeof(char));
479 if (env[1] == NULL) {
483 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
491 /* env variable ends by NULL element */
492 while (env && env[i]) {
499 context_res->env = env;
500 context_res->uid = uid;
501 context_res->gid = pwd.pw_gid;
506 static char **__generate_argv(const char *args)
508 /* Create args vector
509 * req_id + pkgid + args
511 * vector size = # of args +
512 *(req_id + pkgid + NULL termination = 3)
513 * Last value must be NULL for execv.
521 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
522 if (FALSE == ret_parse) {
523 DBG("Failed to split args: %s", args);
524 DBG("messsage: %s", gerr->message);
529 for (i = 0; i < argcp; i++)
530 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
535 void __set_environment(gpointer user_data)
537 user_ctx *ctx = (user_ctx *)user_data;
539 if (set_environement(ctx))
540 DBG("Failed to set env for the user : %d", ctx->uid);
543 static int __fork_and_exec_with_args(char **argv, uid_t uid)
545 user_ctx* user_context;
546 GError *error = NULL;
550 user_context = get_user_context(uid);
552 DBG("Failed to getenv");
556 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
557 __set_environment, (gpointer)user_context, &pid,
560 ERR("Failed to excute backend: %s", error->message);
564 free_user_context(user_context);
569 static int __change_job_info(struct backend_job *job, uid_t uid,
574 pkgmgrinfo_appinfo_h handle = NULL;
575 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
576 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
577 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
578 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
579 job->req_type != REQUEST_TYPE_ENABLE_APP &&
580 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
581 return PMINFO_R_ERROR;
583 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
584 if (ret != PMINFO_R_OK)
585 return PMINFO_R_ERROR;
587 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
588 if (ret != PMINFO_R_OK)
591 if ((job->req_type == REQUEST_TYPE_DISABLE_APP ||
592 job->req_type == REQUEST_TYPE_ENABLE_APP) &&
594 ret = PMINFO_R_ERROR;
596 } else if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
598 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
600 ret = PMINFO_R_ERROR;
604 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
605 if (ret != PMINFO_R_OK)
609 job->appid = strdup(job->pkgid);
611 job->pkgid = strdup(pkgid);
614 pkgmgrinfo_appinfo_destroy_appinfo(handle);
619 static int __process_install(struct backend_job *job)
623 char args[MAX_PKG_ARGS_LEN];
626 backend_cmd = job->backend_path;
627 if (backend_cmd == NULL)
630 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
631 job->req_id, job->pkgid, (int)job->target_uid, job->args);
633 argv = __generate_argv(args);
635 pid = __fork_and_exec_with_args(argv, APPFW_UID);
641 static int __process_mount_install(struct backend_job *job)
645 char args[MAX_PKG_ARGS_LEN];
648 backend_cmd = job->backend_path;
649 if (backend_cmd == NULL)
652 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
653 job->req_id, job->pkgid, (int)job->target_uid, job->args);
655 argv = __generate_argv(args);
657 pid = __fork_and_exec_with_args(argv, APPFW_UID);
663 static int __process_reinstall(struct backend_job *job)
667 char args[MAX_PKG_ARGS_LEN];
670 backend_cmd = job->backend_path;
671 if (backend_cmd == NULL)
674 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
675 job->req_id, job->pkgid, (int)job->target_uid);
676 argv = __generate_argv(args);
678 pid = __fork_and_exec_with_args(argv, APPFW_UID);
685 static int __process_uninstall(struct backend_job *job)
689 char args[MAX_PKG_ARGS_LEN];
692 backend_cmd = job->backend_path;
693 if (backend_cmd == NULL)
696 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
697 job->req_id, job->pkgid, (int)job->target_uid);
698 argv = __generate_argv(args);
700 pid = __fork_and_exec_with_args(argv, APPFW_UID);
707 static int __process_move(struct backend_job *job)
711 char args[MAX_PKG_ARGS_LEN];
714 backend_cmd = job->backend_path;
715 if (backend_cmd == NULL)
718 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
719 job->req_id, job->pkgid, (int)job->target_uid, job->args);
720 argv = __generate_argv(args);
722 pid = __fork_and_exec_with_args(argv, APPFW_UID);
729 static int __process_enable_pkg(struct backend_job *job)
733 char args[MAX_PKG_ARGS_LEN];
734 pkgmgrinfo_pkginfo_h pkginfo_h;
740 backend_cmd = job->backend_path;
741 if (backend_cmd == NULL)
744 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
745 job->pkgid, job->target_uid, &pkginfo_h);
746 if (ret != PMINFO_R_OK) {
747 ERR("Failed to get appinfo");
751 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
752 if (ret != PMINFO_R_OK) {
753 ERR("Failed to get global value");
754 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
758 if ((is_global && job->target_uid != GLOBAL_USER) ||
759 (!is_global && job->target_uid == GLOBAL_USER)) {
760 ERR("Invalid attempt to enable pkg");
761 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
765 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
766 if (ret != PMINFO_R_OK) {
767 ERR("Failed to get readonly value");
768 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
772 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
773 backend_cmd, job->req_id, (int)job->target_uid,
774 job->pkgid, (is_readonly) ? "--preload" : "");
775 argv = __generate_argv(args);
776 pid = __fork_and_exec_with_args(argv, APPFW_UID);
779 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
784 static int __process_disable_pkg(struct backend_job *job)
788 char args[MAX_PKG_ARGS_LEN];
789 pkgmgrinfo_pkginfo_h pkginfo_h;
795 backend_cmd = job->backend_path;
796 if (backend_cmd == NULL)
799 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
800 job->pkgid, job->target_uid, &pkginfo_h);
801 if (ret != PMINFO_R_OK) {
802 ERR("Failed to get appinfo");
806 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
807 if (ret != PMINFO_R_OK) {
808 ERR("Failed to get global value");
809 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
813 if ((is_global && job->target_uid != GLOBAL_USER) ||
814 (!is_global && job->target_uid == GLOBAL_USER)) {
815 ERR("Invalid attempt to disable pkg");
816 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
820 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
821 if (ret != PMINFO_R_OK) {
822 ERR("Failed to get readonly value");
823 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
827 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
828 backend_cmd, job->req_id, (int)job->target_uid,
829 job->pkgid, (is_readonly) ? "--preload" : "");
830 argv = __generate_argv(args);
832 pid = __fork_and_exec_with_args(argv, APPFW_UID);
836 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
840 static int __process_enable_app(struct backend_job *job)
843 bool is_global = false;
845 /* get actual pkgid and replace it to appid which is currently stored
848 ret = __change_job_info(job, job->target_uid, &is_global);
849 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
850 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
851 PKGMGR_INSTALLER_START_KEY_STR,
852 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
854 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
855 PKGMGR_INSTALLER_END_KEY_STR,
856 PKGMGR_INSTALLER_FAIL_EVENT_STR,
861 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
862 PKGMGR_INSTALLER_START_KEY_STR,
863 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
865 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
867 if (ret != PMINFO_R_OK)
868 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
869 PKGMGR_INSTALLER_END_KEY_STR,
870 PKGMGR_INSTALLER_FAIL_EVENT_STR,
873 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
874 PKGMGR_INSTALLER_END_KEY_STR,
875 PKGMGR_INSTALLER_OK_EVENT_STR,
881 static int __process_disable_app(struct backend_job *job)
884 bool is_global = false;
886 /* get actual pkgid and replace it to appid which is currently stored
889 ret = __change_job_info(job, job->target_uid, &is_global);
890 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
891 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
892 PKGMGR_INSTALLER_START_KEY_STR,
893 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
895 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
896 PKGMGR_INSTALLER_END_KEY_STR,
897 PKGMGR_INSTALLER_FAIL_EVENT_STR,
902 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
903 PKGMGR_INSTALLER_START_KEY_STR,
904 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
906 ret = __kill_app(job->appid, job->target_uid);
908 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
909 PKGMGR_INSTALLER_END_KEY_STR,
910 PKGMGR_INSTALLER_FAIL_EVENT_STR,
914 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
916 if (ret != PMINFO_R_OK)
917 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
918 PKGMGR_INSTALLER_END_KEY_STR,
919 PKGMGR_INSTALLER_FAIL_EVENT_STR,
922 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
923 PKGMGR_INSTALLER_END_KEY_STR,
924 PKGMGR_INSTALLER_OK_EVENT_STR,
930 static int __process_enable_global_app_for_uid(struct backend_job *job)
933 bool is_global = true;
935 /* get actual pkgid and replace it to appid which is currently stored
938 ret = __change_job_info(job, job->target_uid, &is_global);
939 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
940 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
941 PKGMGR_INSTALLER_START_KEY_STR,
942 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID,
944 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
945 PKGMGR_INSTALLER_END_KEY_STR,
946 PKGMGR_INSTALLER_FAIL_EVENT_STR,
951 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
952 PKGMGR_INSTALLER_START_KEY_STR,
953 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID,
956 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
957 job->appid, job->target_uid, 0);
958 if (ret != PMINFO_R_OK)
959 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
960 PKGMGR_INSTALLER_END_KEY_STR,
961 PKGMGR_INSTALLER_FAIL_EVENT_STR,
964 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
965 PKGMGR_INSTALLER_END_KEY_STR,
966 PKGMGR_INSTALLER_OK_EVENT_STR,
972 static int __process_disable_global_app_for_uid(struct backend_job *job)
975 bool is_global = true;
977 /* get actual pkgid and replace it to appid which is currently stored
980 ret = __change_job_info(job, GLOBAL_USER, &is_global);
981 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
982 _send_app_signal(job->target_uid, job->req_id,
983 job->pkgid, job->pkgid,
984 PKGMGR_INSTALLER_START_KEY_STR,
985 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID,
987 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
988 PKGMGR_INSTALLER_END_KEY_STR,
989 PKGMGR_INSTALLER_FAIL_EVENT_STR,
994 _send_app_signal(job->target_uid, job->req_id,
995 job->pkgid, job->appid,
996 PKGMGR_INSTALLER_START_KEY_STR,
997 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID,
1000 ret = __kill_app(job->appid, job->target_uid);
1001 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1002 job->appid, job->target_uid, 1);
1004 if (ret != PMINFO_R_OK)
1005 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1006 PKGMGR_INSTALLER_END_KEY_STR,
1007 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1010 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1011 PKGMGR_INSTALLER_END_KEY_STR,
1012 PKGMGR_INSTALLER_OK_EVENT_STR,
1018 static int __process_getsize(struct backend_job *job)
1020 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1022 char args[MAX_PKG_ARGS_LEN];
1025 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1026 backend_cmd, job->pkgid, job->args, job->caller_uid,
1027 job->req_id, job->target_uid);
1028 argv = __generate_argv(args);
1029 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1036 static int __process_cleardata(struct backend_job *job)
1040 char args[MAX_PKG_ARGS_LEN];
1043 backend_cmd = job->backend_path;
1044 if (backend_cmd == NULL)
1047 /* TODO: set movetype */
1048 snprintf(args, sizeof(args), "%s -k %s -c %s -u %d", backend_cmd,
1049 job->req_id, job->pkgid, (int)job->target_uid);
1050 argv = __generate_argv(args);
1052 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1059 static int __process_clearcache(struct backend_job *job)
1061 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1063 char args[MAX_PKG_ARGS_LEN];
1066 snprintf(args, sizeof(args), "%s %s", backend_cmd, job->pkgid);
1067 argv = __generate_argv(args);
1068 pid = __fork_and_exec_with_args(argv, job->target_uid);
1075 static int __process_kill(struct backend_job *job)
1078 pkgmgrinfo_pkginfo_h handle;
1081 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1084 ERR("Failed to get handle");
1085 _return_value_to_caller(job->req_id,
1086 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1090 pdata = calloc(1, sizeof(pkgcmd_data));
1091 if (pdata == NULL) {
1092 ERR("memory alloc failed");
1093 _return_value_to_caller(job->req_id,
1094 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1097 pdata->cmd = strdup("kill");
1098 if (pdata->cmd == NULL) {
1099 ERR("out of memory");
1100 _return_value_to_caller(job->req_id,
1101 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1105 pdata->uid = job->target_uid;
1106 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1107 __pkgcmd_app_cb, pdata, job->target_uid);
1109 _return_value_to_caller(job->req_id,
1110 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1114 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1116 ERR("pkgmgrinfo_appinfo_get_list() failed");
1123 static int __process_check(struct backend_job *job)
1126 pkgmgrinfo_pkginfo_h handle;
1129 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1132 ERR("Failed to get handle");
1133 _return_value_to_caller(job->req_id,
1134 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1138 pdata = calloc(1, sizeof(pkgcmd_data));
1139 if (pdata == NULL) {
1140 ERR("memory alloc failed");
1141 _return_value_to_caller(job->req_id,
1142 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1145 pdata->cmd = strdup("check");
1146 if (pdata->cmd == NULL) {
1147 ERR("out of memory");
1148 _return_value_to_caller(job->req_id,
1149 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1153 pdata->uid = job->target_uid;
1154 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1155 __pkgcmd_app_cb, pdata, job->target_uid);
1157 _return_value_to_caller(job->req_id,
1158 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1162 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1164 ERR("pkgmgrinfo_appinfo_get_list() failed");
1171 static int __process_generate_license_request(struct backend_job *job)
1175 char req_data[MAX_PKG_ARGS_LEN];
1176 unsigned int req_data_len;
1177 char license_url[MAX_PKG_ARGS_LEN];
1178 unsigned int license_url_len;
1180 resp_data = job->args;
1181 req_data_len = sizeof(req_data);
1182 license_url_len = sizeof(license_url);
1184 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1185 req_data, &req_data_len, license_url, &license_url_len);
1186 if (ret != TADC_SUCCESS) {
1187 ERR("drm_tizen_generate_license_request failed: %d", ret);
1188 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1189 PKGMGR_R_ESYSTEM, "", ""));
1193 _return_value_to_caller(job->req_id,
1194 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1200 static int __process_register_license(struct backend_job *job)
1205 resp_data = job->args;
1207 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1208 if (ret != TADC_SUCCESS) {
1209 ERR("drm_tizen_register_license failed: %d", ret);
1210 _return_value_to_caller(job->req_id,
1211 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1215 _return_value_to_caller(job->req_id,
1216 g_variant_new("(i)", PKGMGR_R_OK));
1221 static int __process_decrypt_package(struct backend_job *job)
1224 char *drm_file_path;
1225 char *decrypted_file_path;
1227 drm_file_path = job->pkgid;
1228 decrypted_file_path = job->args;
1230 /* TODO: check ownership of decrypted file */
1231 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1232 decrypted_file_path, strlen(decrypted_file_path));
1233 if (ret != TADC_SUCCESS) {
1234 ERR("drm_tizen_register_license failed: %d", ret);
1235 _return_value_to_caller(job->req_id,
1236 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1240 _return_value_to_caller(job->req_id,
1241 g_variant_new("(i)", PKGMGR_R_OK));
1246 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1249 bool is_global = false;
1252 ret = __change_job_info(job, job->target_uid, &is_global);
1253 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1256 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1257 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1258 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1259 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1262 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1264 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1265 job->appid, job->target_uid, flag);
1266 if (ret != PMINFO_R_OK)
1267 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1268 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1269 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1272 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1273 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1274 PKGMGR_INSTALLER_OK_EVENT_STR,
1280 static int __process_set_restriction_mode(struct backend_job *job)
1285 mode = atoi(job->args);
1286 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1288 _return_value_to_caller(job->req_id,
1289 g_variant_new("(i)", ret));
1294 static int __process_unset_restriction_mode(struct backend_job *job)
1299 mode = atoi(job->args);
1300 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1302 _return_value_to_caller(job->req_id,
1303 g_variant_new("(i)", ret));
1308 static int __process_get_restriction_mode(struct backend_job *job)
1313 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1315 _return_value_to_caller(job->req_id,
1316 g_variant_new("(ii)", mode, ret));
1321 static int __process_set_app_label(struct backend_job *job)
1325 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1326 job->target_uid, job->args);
1327 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1332 gboolean queue_job(void *data)
1334 struct backend_job *job = NULL;
1338 /* Pop a job from queue */
1339 for (x = 0; x < num_of_backends; x++) {
1340 if (__is_backend_busy(x))
1343 job = _pop_queue(x);
1348 /* all backend messages queue are empty or busy */
1349 if (x == num_of_backends || job == NULL) {
1354 /* set current backend job */
1355 DBG("handle request type [%d]", job->req_type);
1357 #ifdef TIZEN_FEATURE_CSR
1358 if (job->req_type == REQUEST_TYPE_INSTALL ||
1359 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1360 job->req_type == REQUEST_TYPE_REINSTALL) {
1361 ret = __check_csr(job->pkgid);
1364 _send_fail_signal(job);
1365 _free_backend_job(job);
1371 switch (job->req_type) {
1372 case REQUEST_TYPE_INSTALL:
1373 __set_backend_busy(x);
1374 ret = __process_install(job);
1375 g_hash_table_insert(backend_info_table, (gpointer)ret,
1378 case REQUEST_TYPE_MOUNT_INSTALL:
1379 __set_backend_busy(x);
1380 ret = __process_mount_install(job);
1381 g_hash_table_insert(backend_info_table, (gpointer)ret,
1384 case REQUEST_TYPE_REINSTALL:
1385 __set_backend_busy(x);
1386 ret = __process_reinstall(job);
1387 g_hash_table_insert(backend_info_table, (gpointer)ret,
1390 case REQUEST_TYPE_UNINSTALL:
1391 __set_backend_busy(x);
1392 ret = __process_uninstall(job);
1393 g_hash_table_insert(backend_info_table, (gpointer)ret,
1396 case REQUEST_TYPE_MOVE:
1397 __set_backend_busy(x);
1398 ret = __process_move(job);
1399 g_hash_table_insert(backend_info_table, (gpointer)ret,
1402 case REQUEST_TYPE_ENABLE_PKG:
1403 __set_backend_busy(x);
1404 ret = __process_enable_pkg(job);
1406 _send_fail_signal(job);
1407 __set_backend_free(x);
1408 _free_backend_job(job);
1410 g_hash_table_insert(backend_info_table, (gpointer)ret,
1414 case REQUEST_TYPE_DISABLE_PKG:
1415 __set_backend_busy(x);
1416 ret = __process_disable_pkg(job);
1418 _send_fail_signal(job);
1419 __set_backend_free(x);
1420 _free_backend_job(job);
1422 g_hash_table_insert(backend_info_table, (gpointer)ret,
1426 case REQUEST_TYPE_ENABLE_APP:
1427 ret = __process_enable_app(job);
1428 _free_backend_job(job);
1430 case REQUEST_TYPE_DISABLE_APP:
1431 ret = __process_disable_app(job);
1432 _free_backend_job(job);
1434 case REQUEST_TYPE_GETSIZE:
1435 __set_backend_busy(x);
1436 ret = __process_getsize(job);
1437 g_hash_table_insert(backend_info_table, (gpointer)ret,
1440 case REQUEST_TYPE_CLEARDATA:
1441 __set_backend_busy(x);
1442 ret = __process_cleardata(job);
1443 g_hash_table_insert(backend_info_table, (gpointer)ret,
1446 case REQUEST_TYPE_CLEARCACHE:
1447 __set_backend_busy(x);
1448 ret = __process_clearcache(job);
1449 g_hash_table_insert(backend_info_table, (gpointer)ret,
1452 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1453 ret = __process_enable_global_app_for_uid(job);
1454 _free_backend_job(job);
1456 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1457 ret = __process_disable_global_app_for_uid(job);
1458 _free_backend_job(job);
1460 case REQUEST_TYPE_KILL:
1461 ret = __process_kill(job);
1462 _free_backend_job(job);
1464 case REQUEST_TYPE_CHECK:
1465 ret = __process_check(job);
1466 _free_backend_job(job);
1468 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1469 ret = __process_generate_license_request(job);
1470 _free_backend_job(job);
1472 case REQUEST_TYPE_REGISTER_LICENSE:
1473 ret = __process_register_license(job);
1474 _free_backend_job(job);
1476 case REQUEST_TYPE_DECRYPT_PACKAGE:
1477 ret = __process_decrypt_package(job);
1478 _free_backend_job(job);
1480 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1481 ret = __process_update_app_splash_screen(job, 1);
1482 _free_backend_job(job);
1484 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1485 ret = __process_update_app_splash_screen(job, 0);
1486 _free_backend_job(job);
1488 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1489 ret = __process_set_restriction_mode(job);
1490 _free_backend_job(job);
1492 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1493 ret = __process_unset_restriction_mode(job);
1494 _free_backend_job(job);
1496 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1497 ret = __process_get_restriction_mode(job);
1498 _free_backend_job(job);
1500 case REQUEST_TYPE_SET_APP_LABEL:
1501 ret = __process_set_app_label(job);
1502 _free_backend_job(job);
1512 int main(int argc, char *argv[])
1516 DBG("server start");
1518 r = _init_backend_queue();
1520 DBG("Queue Initialization Failed");
1524 r = __init_backend_info();
1526 DBG("backend info init failed");
1530 r = _init_request_handler();
1532 ERR("dbus init failed");
1536 if (__register_signal_handler()) {
1537 ERR("failed to register signal handler");
1541 #if !GLIB_CHECK_VERSION(2, 35, 0)
1544 mainloop = g_main_loop_new(NULL, FALSE);
1546 ERR("g_main_loop_new failed");
1550 DBG("Main loop is created.");
1552 g_main_loop_run(mainloop);
1554 DBG("Quit main loop.");
1555 _fini_request_handler();
1556 __fini_backend_info();
1557 _fini_backend_queue();
1559 DBG("package manager server terminated.");