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;
125 struct getsize_sync_extra_info *extra_getsize_info =
126 (struct getsize_sync_extra_info *)job->extra_data;
128 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
129 if (s != G_IO_STATUS_NORMAL) {
130 ERR("getsize fd read failed: %s", err->message);
134 if (strlen(buf) == 0) {
142 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
143 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
145 unlink(extra_getsize_info->getsize_fifo);
146 free(extra_getsize_info->getsize_fifo);
147 extra_getsize_info->getsize_fifo = NULL;
152 static int __setup_size_info_io(struct backend_job *job)
155 struct getsize_sync_extra_info *extra_getsize_info =
156 (struct getsize_sync_extra_info *)job->extra_data;
158 extra_getsize_info->getsize_fd = open(extra_getsize_info->getsize_fifo,
159 O_RDONLY | O_NONBLOCK);
160 if (extra_getsize_info->getsize_fd < 0) {
161 ERR("failed to open the fifo(%s), errno(%d)",
162 extra_getsize_info->getsize_fifo, errno);
166 extra_getsize_info->getsize_io =
167 g_io_channel_unix_new(extra_getsize_info->getsize_fd);
168 if (!extra_getsize_info->getsize_io)
170 g_io_channel_set_encoding(extra_getsize_info->getsize_io, NULL, NULL);
171 g_io_channel_set_buffered(extra_getsize_info->getsize_io, FALSE);
172 getsize_wid = g_io_add_watch_full(extra_getsize_info->getsize_io,
173 G_PRIORITY_HIGH, G_IO_IN, getsize_io_handler, job, NULL);
175 ERR("failed to add io watch");
182 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
188 struct signalfd_siginfo fdsi;
189 struct backend_job *job;
190 struct getsize_sync_extra_info *extra_getsize_info;
194 s = g_io_channel_read_chars(io, (gchar *)&fdsi,
195 sizeof(struct signalfd_siginfo), &len, &err);
196 if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
197 ERR("Signal read failed");
202 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
203 job = (struct backend_job *)g_hash_table_lookup(
204 backend_info_table, (gconstpointer)pid);
206 ERR("Unknown child exit");
210 __set_backend_free(job->backend_slot);
211 if (WIFSIGNALED(status)) {
212 _send_fail_signal(job);
213 INFO("backend[%s][%d] exit with signal[%d]",
214 job->backend_type, pid, WTERMSIG(status));
215 } else if (WEXITSTATUS(status)) {
216 INFO("backend[%s][%d] exit with error",
217 job->backend_type, pid);
219 INFO("backend[%s][%d] exit", job->backend_type, pid);
222 if (job->req_type == REQUEST_TYPE_GETSIZE_SYNC &&
225 (struct getsize_sync_extra_info *)job->extra_data;
226 if (extra_getsize_info->getsize_fifo) {
227 ERR("invalid backend close");
228 _return_value_to_caller(job->req_id,
229 g_variant_new("(ix)",
230 PKGMGR_R_ERROR, -1));
233 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
235 g_idle_add(queue_job, NULL);
240 static int __init_backend_info(void)
242 backend_info_table = g_hash_table_new_full(g_direct_hash,
243 g_direct_equal, NULL,
244 (GDestroyNotify)_free_backend_job);
249 static void __fini_backend_info(void)
251 /*Free backend info */
252 g_hash_table_destroy(backend_info_table);
255 static int __register_signal_handler(void)
261 sigaddset(&mask, SIGCHLD);
263 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
264 ERR("sigprocmask failed");
268 sfd = signalfd(-1, &mask, SFD_NONBLOCK);
270 ERR("signalfd failed");
274 sio = g_io_channel_unix_new(sfd);
275 g_io_channel_set_close_on_unref(sio, TRUE);
276 g_io_channel_set_encoding(sio, NULL, NULL);
277 g_io_channel_set_buffered(sio, FALSE);
278 swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
280 g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, exit_server, NULL, NULL);
285 static int __check_backend_status_for_exit(void)
288 for (i = 0; i < num_of_backends; i++) {
289 if (__is_backend_busy(i))
295 static int __check_queue_status_for_exit(void)
298 for (i = 0; i < num_of_backends; i++) {
299 if (_is_queue_empty(i) == 0)
305 gboolean exit_server(void *data)
307 DBG("exit_server Start");
308 if (__check_backend_status_for_exit() &&
309 __check_queue_status_for_exit() && !is_drm_busy) {
310 g_main_loop_quit(mainloop);
316 #ifdef TIZEN_FEATURE_CSR
317 static int __check_csr(const char *path)
319 csr_cs_context_h context = NULL;
320 csr_cs_malware_h detected = NULL;
323 ret = csr_cs_context_create(&context);
324 if (ret != CSR_ERROR_NONE) {
325 ERR("Failed to create csr context");
330 ret = csr_cs_scan_file(context, path, &detected);
331 DBG("CSR result[%d]", ret);
333 csr_cs_context_destroy(context);
334 if (detected != NULL) {
335 ERR("CSR Denied[%s] Installation", path);
344 static int __kill_app(char *appid, uid_t uid)
350 is_running = aul_app_is_running_for_uid(appid, uid);
351 /* app is not running */
355 pid = aul_app_get_pid_for_uid(appid, uid);
359 ret = aul_terminate_pid_for_uid(pid, uid);
360 if (ret != AUL_R_OK) {
361 ERR("failed to terminate app(%d)", appid);
368 static int __check_app(char *appid, uid_t uid)
373 is_running = aul_app_is_running_for_uid(appid, uid);
377 pid = aul_app_get_pid_for_uid(appid, uid);
382 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
388 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
390 if (handle == NULL) {
391 perror("appinfo handle is NULL\n");
394 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
396 perror("Failed to get app exec path\n");
399 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
401 perror("Failed to get appid\n");
404 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
406 perror("Failed to get pkgid\n");
410 if (strcmp(pdata->cmd, "kill") == 0) {
411 pdata->pid = __check_app(appid, pdata->uid);
413 ret = __kill_app(appid, pdata->uid);
414 } else if (strcmp(pdata->cmd, "check") == 0) {
415 pdata->pid = __check_app(appid, pdata->uid);
421 void free_user_context(user_ctx *ctx)
428 /* env variable ends by NULL element */
438 int set_environement(user_ctx *ctx)
449 if (ctx->uid != APPFW_UID) {
450 if (setuid(ctx->uid)) {
451 ERR("setuid failed: %d", errno);
455 if (setgid(ctx->gid)) {
456 ERR("setgid failed: %d", errno);
461 n = getgroups(0, NULL);
463 ERR("Failed to get the number of supplementary group IDs");
467 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
468 if (groups == NULL) {
469 ERR("out of memory");
473 n = getgroups(n, groups);
475 ERR("Failed to get list of supplementary group IDs");
480 groups[n++] = EXT_STORAGE_GROUP;
481 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
482 groups[n++] = MEDIA_STORAGE_GROUP;
484 if (setgroups(n, groups) < 0) {
485 ERR("setgroups failed: %d", errno);
492 /* env variable ends by NULL element */
494 if (putenv(env[i]) != 0)
501 user_ctx *get_user_context(uid_t uid)
503 /* we can use getpwnam because this is used only after a
504 * fork and just before an execv
505 * No concurrencial call can corrupt the data
506 * returned by getpwuid
508 user_ctx *context_res;
510 char buf[1024] = {0, };
511 struct passwd pwd, *result;
516 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
517 if (ret != 0 || result == NULL)
521 context_res = (user_ctx *)malloc(sizeof(user_ctx));
526 env = (char **)malloc(3 * sizeof(char *));
531 /* Build environment context */
532 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
533 env[0] = (char *)malloc((len + 1) * sizeof(char));
534 if (env[0] == NULL) {
538 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
539 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
540 env[1] = (char *)malloc((len + 1) * sizeof(char));
541 if (env[1] == NULL) {
545 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
553 /* env variable ends by NULL element */
554 while (env && env[i]) {
561 context_res->env = env;
562 context_res->uid = uid;
563 context_res->gid = pwd.pw_gid;
568 static char **__generate_argv(const char *args)
570 /* Create args vector
571 * req_id + pkgid + args
573 * vector size = # of args +
574 *(req_id + pkgid + NULL termination = 3)
575 * Last value must be NULL for execv.
583 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
584 if (FALSE == ret_parse) {
585 ERR("Failed to split args: %s", args);
586 ERR("messsage: %s", gerr->message);
591 for (i = 0; i < argcp; i++)
592 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
597 void __set_environment(gpointer user_data)
599 user_ctx *ctx = (user_ctx *)user_data;
601 if (set_environement(ctx))
602 ERR("Failed to set env for the user : %d", ctx->uid);
605 static int __fork_and_exec_with_args(char **argv, uid_t uid)
607 user_ctx *user_context;
608 GError *error = NULL;
612 user_context = get_user_context(uid);
614 ERR("Failed to getenv");
618 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
619 __set_environment, (gpointer)user_context, &pid,
622 ERR("Failed to excute backend: %s", error->message);
624 free_user_context(user_context);
628 free_user_context(user_context);
633 static int __change_job_info(struct backend_job *job, uid_t uid,
638 pkgmgrinfo_appinfo_h handle = NULL;
639 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
640 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
641 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
642 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
643 job->req_type != REQUEST_TYPE_ENABLE_APP &&
644 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
645 return PMINFO_R_ERROR;
647 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
648 if (ret != PMINFO_R_OK)
649 return PMINFO_R_ERROR;
651 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
652 if (ret != PMINFO_R_OK)
655 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
657 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
659 ret = PMINFO_R_ERROR;
663 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
664 if (ret != PMINFO_R_OK)
668 job->appid = strdup(job->pkgid);
670 job->pkgid = strdup(pkgid);
673 pkgmgrinfo_appinfo_destroy_appinfo(handle);
678 static int __process_install(struct backend_job *job)
682 char args[MAX_PKG_ARGS_LEN];
687 backend_cmd = job->backend_path;
688 if (backend_cmd == NULL)
691 req_id = g_shell_quote(job->req_id);
692 pkgid = g_shell_quote(job->pkgid);
693 if (!req_id || !pkgid)
696 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
697 req_id, pkgid, (int)job->target_uid, job->args);
699 argv = __generate_argv(args);
701 pid = __fork_and_exec_with_args(argv, APPFW_UID);
709 static int __process_mount_install(struct backend_job *job)
713 char args[MAX_PKG_ARGS_LEN];
718 backend_cmd = job->backend_path;
719 if (backend_cmd == NULL)
722 req_id = g_shell_quote(job->req_id);
723 pkgid = g_shell_quote(job->pkgid);
724 if (!req_id || !pkgid)
727 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
728 req_id, pkgid, (int)job->target_uid, job->args);
730 argv = __generate_argv(args);
732 pid = __fork_and_exec_with_args(argv, APPFW_UID);
740 static int __process_reinstall(struct backend_job *job)
744 char args[MAX_PKG_ARGS_LEN];
749 backend_cmd = job->backend_path;
750 if (backend_cmd == NULL)
753 req_id = g_shell_quote(job->req_id);
754 pkgid = g_shell_quote(job->pkgid);
755 if (!req_id || !pkgid)
758 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
759 req_id, pkgid, (int)job->target_uid);
760 argv = __generate_argv(args);
762 pid = __fork_and_exec_with_args(argv, APPFW_UID);
771 static int __process_uninstall(struct backend_job *job)
775 char args[MAX_PKG_ARGS_LEN];
778 backend_cmd = job->backend_path;
779 if (backend_cmd == NULL)
782 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
783 job->req_id, job->pkgid, (int)job->target_uid);
784 argv = __generate_argv(args);
786 pid = __fork_and_exec_with_args(argv, APPFW_UID);
793 static int __process_move(struct backend_job *job)
797 char args[MAX_PKG_ARGS_LEN];
800 backend_cmd = job->backend_path;
801 if (backend_cmd == NULL)
804 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
805 job->req_id, job->pkgid, (int)job->target_uid, job->args);
806 argv = __generate_argv(args);
808 pid = __fork_and_exec_with_args(argv, APPFW_UID);
815 static int __process_enable_pkg(struct backend_job *job)
819 char args[MAX_PKG_ARGS_LEN];
820 pkgmgrinfo_pkginfo_h pkginfo_h;
826 backend_cmd = job->backend_path;
827 if (backend_cmd == NULL)
830 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
831 job->pkgid, job->target_uid, &pkginfo_h);
832 if (ret != PMINFO_R_OK) {
833 ERR("Failed to get appinfo");
837 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
838 if (ret != PMINFO_R_OK) {
839 ERR("Failed to get global value");
840 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
844 if ((is_global && job->target_uid != GLOBAL_USER) ||
845 (!is_global && job->target_uid == GLOBAL_USER)) {
846 ERR("Invalid attempt to enable pkg");
847 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
851 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
852 if (ret != PMINFO_R_OK) {
853 ERR("Failed to get readonly value");
854 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
858 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
859 backend_cmd, job->req_id, (int)job->target_uid,
860 job->pkgid, (is_readonly) ? "--preload" : "");
861 argv = __generate_argv(args);
862 pid = __fork_and_exec_with_args(argv, APPFW_UID);
865 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
870 static int __process_disable_pkg(struct backend_job *job)
874 char args[MAX_PKG_ARGS_LEN];
875 pkgmgrinfo_pkginfo_h pkginfo_h;
881 backend_cmd = job->backend_path;
882 if (backend_cmd == NULL)
885 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
886 job->pkgid, job->target_uid, &pkginfo_h);
887 if (ret != PMINFO_R_OK) {
888 ERR("Failed to get appinfo");
892 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
893 if (ret != PMINFO_R_OK) {
894 ERR("Failed to get global value");
895 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
899 if ((is_global && job->target_uid != GLOBAL_USER) ||
900 (!is_global && job->target_uid == GLOBAL_USER)) {
901 ERR("Invalid attempt to disable pkg");
902 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
906 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
907 if (ret != PMINFO_R_OK) {
908 ERR("Failed to get readonly value");
909 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
913 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
914 backend_cmd, job->req_id, (int)job->target_uid,
915 job->pkgid, (is_readonly) ? "--preload" : "");
916 argv = __generate_argv(args);
918 pid = __fork_and_exec_with_args(argv, APPFW_UID);
922 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
926 static int __process_register_pkg_update_info(struct backend_job *job)
930 if (!job->extra_data) {
931 _return_value_to_caller(job->req_id,
932 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
936 ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
937 (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
938 if (ret == PMINFO_R_OK)
939 _return_value_to_caller(job->req_id,
940 g_variant_new("(i)", PKGMGR_R_OK));
942 _return_value_to_caller(job->req_id,
943 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
945 pkgmgrinfo_updateinfo_destroy(job->extra_data);
946 job->extra_data = NULL;
951 static int __process_unregister_pkg_update_info(struct backend_job *job)
953 int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
954 (job->pkgid, job->target_uid);
956 if (ret == PMINFO_R_OK)
957 _return_value_to_caller(job->req_id,
958 g_variant_new("(i)", PKGMGR_R_OK));
960 _return_value_to_caller(job->req_id,
961 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
965 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
967 int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
970 if (ret != PMINFO_R_OK) {
971 _return_value_to_caller(job->req_id,
972 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
976 if (__is_admin_user(job->caller_uid)) {
977 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
979 if (ret != PMINFO_R_OK) {
980 _return_value_to_caller(job->req_id,
981 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
985 _return_value_to_caller(job->req_id,
986 g_variant_new("(i)", PKGMGR_R_OK));
991 static int __process_enable_app(struct backend_job *job)
994 bool is_global = false;
996 /* get actual pkgid and replace it to appid which is currently stored
999 ret = __change_job_info(job, job->target_uid, &is_global);
1000 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1001 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1002 PKGMGR_INSTALLER_START_KEY_STR,
1003 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1005 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1006 PKGMGR_INSTALLER_END_KEY_STR,
1007 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1012 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1013 PKGMGR_INSTALLER_START_KEY_STR,
1014 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1016 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1017 job->target_uid, 0);
1018 if (ret != PMINFO_R_OK)
1019 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1020 PKGMGR_INSTALLER_END_KEY_STR,
1021 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1024 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1025 PKGMGR_INSTALLER_END_KEY_STR,
1026 PKGMGR_INSTALLER_OK_EVENT_STR,
1032 static int __process_disable_app(struct backend_job *job)
1035 bool is_global = false;
1037 /* get actual pkgid and replace it to appid which is currently stored
1040 ret = __change_job_info(job, job->target_uid, &is_global);
1041 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1042 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1043 PKGMGR_INSTALLER_START_KEY_STR,
1044 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1046 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1047 PKGMGR_INSTALLER_END_KEY_STR,
1048 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1053 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1054 PKGMGR_INSTALLER_START_KEY_STR,
1055 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1057 ret = __kill_app(job->appid, job->target_uid);
1059 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1060 PKGMGR_INSTALLER_END_KEY_STR,
1061 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1065 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1066 job->target_uid, 1);
1067 if (ret != PMINFO_R_OK)
1068 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1069 PKGMGR_INSTALLER_END_KEY_STR,
1070 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1073 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1074 PKGMGR_INSTALLER_END_KEY_STR,
1075 PKGMGR_INSTALLER_OK_EVENT_STR,
1081 static int __process_enable_global_app_for_uid(struct backend_job *job)
1084 bool is_global = true;
1086 /* get actual pkgid and replace it to appid which is currently stored
1089 ret = __change_job_info(job, job->target_uid, &is_global);
1090 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1091 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1092 PKGMGR_INSTALLER_START_KEY_STR,
1093 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1095 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1096 PKGMGR_INSTALLER_END_KEY_STR,
1097 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1102 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1103 PKGMGR_INSTALLER_START_KEY_STR,
1104 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1107 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1108 job->appid, job->target_uid, 0);
1109 if (ret != PMINFO_R_OK)
1110 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1111 PKGMGR_INSTALLER_END_KEY_STR,
1112 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1115 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1116 PKGMGR_INSTALLER_END_KEY_STR,
1117 PKGMGR_INSTALLER_OK_EVENT_STR,
1123 static int __process_disable_global_app_for_uid(struct backend_job *job)
1126 bool is_global = true;
1128 /* get actual pkgid and replace it to appid which is currently stored
1131 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1132 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1133 _send_app_signal(job->target_uid, job->req_id,
1134 job->pkgid, job->pkgid,
1135 PKGMGR_INSTALLER_START_KEY_STR,
1136 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1138 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1139 PKGMGR_INSTALLER_END_KEY_STR,
1140 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1145 _send_app_signal(job->target_uid, job->req_id,
1146 job->pkgid, job->appid,
1147 PKGMGR_INSTALLER_START_KEY_STR,
1148 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1151 ret = __kill_app(job->appid, job->target_uid);
1152 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1153 job->appid, job->target_uid, 1);
1155 if (ret != PMINFO_R_OK)
1156 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1157 PKGMGR_INSTALLER_END_KEY_STR,
1158 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1161 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1162 PKGMGR_INSTALLER_END_KEY_STR,
1163 PKGMGR_INSTALLER_OK_EVENT_STR,
1169 static int __process_getsize(struct backend_job *job)
1171 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1173 char args[MAX_PKG_ARGS_LEN];
1176 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1177 backend_cmd, job->pkgid, job->args, job->caller_uid,
1178 job->req_id, job->target_uid);
1179 argv = __generate_argv(args);
1180 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1187 static int __process_getsize_sync(struct backend_job *job)
1189 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1191 char args[MAX_PKG_ARGS_LEN];
1192 char fifo_path[PATH_MAX];
1193 struct getsize_sync_extra_info *extra_getsize_info;
1196 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1199 extra_getsize_info = calloc(1, sizeof(struct getsize_sync_extra_info));
1200 if (!extra_getsize_info) {
1201 ERR("memory alloc failed");
1205 extra_getsize_info->getsize_fifo = strdup(fifo_path);
1206 if (!extra_getsize_info->getsize_fifo) {
1207 ERR("out of memory");
1211 if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1212 ERR("failed to mkfifo");
1215 job->extra_data = extra_getsize_info;
1217 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1218 backend_cmd, job->pkgid, job->args, job->caller_uid,
1219 job->req_id, job->target_uid);
1220 argv = __generate_argv(args);
1221 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1226 ERR("failed to execute backend");
1229 if (__setup_size_info_io(job) < 0) {
1230 ERR("failed to setup io handler");
1237 _return_value_to_caller(job->req_id,
1238 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1242 static int __process_cleardata(struct backend_job *job)
1244 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1246 char args[MAX_PKG_ARGS_LEN];
1249 if ((int)job->target_uid < REGULAR_USER)
1252 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1253 backend_cmd, job->pkgid, job->target_uid);
1254 argv = __generate_argv(args);
1255 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1261 static int __process_clearcache(struct backend_job *job)
1263 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1265 char args[MAX_PKG_ARGS_LEN];
1268 if ((int)job->target_uid < REGULAR_USER)
1271 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1272 backend_cmd, job->pkgid, job->target_uid);
1273 argv = __generate_argv(args);
1274 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1280 static int __process_kill(struct backend_job *job)
1283 pkgmgrinfo_pkginfo_h handle;
1286 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1289 ERR("Failed to get handle");
1290 _return_value_to_caller(job->req_id,
1291 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1295 pdata = calloc(1, sizeof(pkgcmd_data));
1296 if (pdata == NULL) {
1297 ERR("memory alloc failed");
1298 _return_value_to_caller(job->req_id,
1299 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1302 pdata->cmd = strdup("kill");
1303 if (pdata->cmd == NULL) {
1304 ERR("out of memory");
1305 _return_value_to_caller(job->req_id,
1306 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1310 pdata->uid = job->target_uid;
1311 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1312 __pkgcmd_app_cb, pdata, job->target_uid);
1314 _return_value_to_caller(job->req_id,
1315 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1319 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1321 ERR("pkgmgrinfo_appinfo_get_list() failed");
1328 static int __process_check(struct backend_job *job)
1331 pkgmgrinfo_pkginfo_h handle;
1334 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1337 ERR("Failed to get handle");
1338 _return_value_to_caller(job->req_id,
1339 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1343 pdata = calloc(1, sizeof(pkgcmd_data));
1344 if (pdata == NULL) {
1345 ERR("memory alloc failed");
1346 _return_value_to_caller(job->req_id,
1347 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1350 pdata->cmd = strdup("check");
1351 if (pdata->cmd == NULL) {
1352 ERR("out of memory");
1353 _return_value_to_caller(job->req_id,
1354 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1358 pdata->uid = job->target_uid;
1359 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1360 __pkgcmd_app_cb, pdata, job->target_uid);
1362 _return_value_to_caller(job->req_id,
1363 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1367 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1369 ERR("pkgmgrinfo_appinfo_get_list() failed");
1376 static int __process_generate_license_request(struct backend_job *job)
1380 char req_data[MAX_PKG_ARGS_LEN];
1381 unsigned int req_data_len;
1382 char license_url[MAX_PKG_ARGS_LEN];
1383 unsigned int license_url_len;
1385 resp_data = job->args;
1386 req_data_len = sizeof(req_data);
1387 license_url_len = sizeof(license_url);
1389 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1390 req_data, &req_data_len, license_url, &license_url_len);
1391 if (ret != TADC_SUCCESS) {
1392 ERR("drm_tizen_generate_license_request failed: %d", ret);
1393 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1394 PKGMGR_R_ESYSTEM, "", ""));
1395 is_drm_busy = false;
1399 _return_value_to_caller(job->req_id,
1400 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1406 static int __process_register_license(struct backend_job *job)
1411 resp_data = job->args;
1413 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1414 if (ret != TADC_SUCCESS) {
1415 ERR("drm_tizen_register_license failed: %d", ret);
1416 _return_value_to_caller(job->req_id,
1417 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1418 is_drm_busy = false;
1422 _return_value_to_caller(job->req_id,
1423 g_variant_new("(i)", PKGMGR_R_OK));
1428 static int __process_decrypt_package(struct backend_job *job)
1431 char *drm_file_path;
1432 char *decrypted_file_path;
1434 drm_file_path = job->pkgid;
1435 decrypted_file_path = job->args;
1437 /* TODO: check ownership of decrypted file */
1438 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1439 decrypted_file_path, strlen(decrypted_file_path));
1440 if (ret != TADC_SUCCESS) {
1441 ERR("drm_tizen_register_license failed: %d", ret);
1442 _return_value_to_caller(job->req_id,
1443 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1444 is_drm_busy = false;
1448 _return_value_to_caller(job->req_id,
1449 g_variant_new("(i)", PKGMGR_R_OK));
1450 is_drm_busy = false;
1455 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1458 bool is_global = false;
1461 ret = __change_job_info(job, job->target_uid, &is_global);
1462 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1465 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1466 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1467 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1468 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1471 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1473 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1474 job->appid, job->target_uid, flag);
1475 if (ret != PMINFO_R_OK)
1476 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1477 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1478 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1481 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1482 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1483 PKGMGR_INSTALLER_OK_EVENT_STR,
1489 static int __process_set_restriction_mode(struct backend_job *job)
1494 mode = atoi(job->args);
1495 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1497 _return_value_to_caller(job->req_id,
1498 g_variant_new("(i)", ret));
1503 static int __process_unset_restriction_mode(struct backend_job *job)
1508 mode = atoi(job->args);
1509 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1511 _return_value_to_caller(job->req_id,
1512 g_variant_new("(i)", ret));
1517 static int __process_get_restriction_mode(struct backend_job *job)
1522 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1524 _return_value_to_caller(job->req_id,
1525 g_variant_new("(ii)", mode, ret));
1530 static int __process_set_app_label(struct backend_job *job)
1534 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1535 job->target_uid, job->args);
1536 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1541 static int __process_migrate_external_image(struct backend_job *job)
1545 char args[MAX_PKG_ARGS_LEN];
1548 backend_cmd = job->backend_path;
1549 if (backend_cmd == NULL)
1552 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1553 backend_cmd, job->req_id, job->pkgid,
1554 (int)job->target_uid, job->args);
1556 argv = __generate_argv(args);
1558 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1564 static int __post_process(int ret, int x, struct backend_job *job)
1567 __set_backend_free(x);
1568 _free_backend_job(job);
1570 g_hash_table_insert(backend_info_table, (gpointer)ret,
1576 gboolean queue_job(void *data)
1578 struct backend_job *job = NULL;
1582 /* Pop a job from queue */
1583 for (x = 0; x < num_of_backends; x++) {
1584 if (__is_backend_busy(x))
1587 job = _pop_queue(x);
1592 /* all backend messages queue are empty or busy */
1593 if (x == num_of_backends || job == NULL) {
1594 DBG("no job available");
1598 /* set current backend job */
1599 DBG("handle request type [%d]", job->req_type);
1601 #ifdef TIZEN_FEATURE_CSR
1602 if (job->req_type == REQUEST_TYPE_INSTALL ||
1603 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1604 job->req_type == REQUEST_TYPE_REINSTALL) {
1605 ret = __check_csr(job->pkgid);
1608 _send_fail_signal(job);
1609 _free_backend_job(job);
1615 switch (job->req_type) {
1616 case REQUEST_TYPE_INSTALL:
1617 __set_backend_busy(x);
1618 ret = __process_install(job);
1619 __post_process(ret, x, job);
1621 case REQUEST_TYPE_MOUNT_INSTALL:
1622 __set_backend_busy(x);
1623 ret = __process_mount_install(job);
1624 __post_process(ret, x, job);
1626 case REQUEST_TYPE_REINSTALL:
1627 __set_backend_busy(x);
1628 ret = __process_reinstall(job);
1629 __post_process(ret, x, job);
1631 case REQUEST_TYPE_UNINSTALL:
1632 __set_backend_busy(x);
1633 ret = __process_uninstall(job);
1634 __post_process(ret, x, job);
1636 case REQUEST_TYPE_MOVE:
1637 __set_backend_busy(x);
1638 ret = __process_move(job);
1639 __post_process(ret, x, job);
1641 case REQUEST_TYPE_ENABLE_PKG:
1642 __set_backend_busy(x);
1643 ret = __process_enable_pkg(job);
1645 _send_fail_signal(job);
1646 __post_process(ret, x, job);
1648 case REQUEST_TYPE_DISABLE_PKG:
1649 __set_backend_busy(x);
1650 ret = __process_disable_pkg(job);
1652 _send_fail_signal(job);
1653 __post_process(ret, x, job);
1655 case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1656 ret = __process_register_pkg_update_info(job);
1657 __free_extra_info(job);
1658 _free_backend_job(job);
1660 case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1661 ret = __process_unregister_pkg_update_info(job);
1662 _free_backend_job(job);
1664 case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1665 ret = __process_unregister_all_pkg_update_info(job);
1666 _free_backend_job(job);
1668 case REQUEST_TYPE_ENABLE_APP:
1669 ret = __process_enable_app(job);
1670 _free_backend_job(job);
1672 case REQUEST_TYPE_DISABLE_APP:
1673 ret = __process_disable_app(job);
1674 _free_backend_job(job);
1676 case REQUEST_TYPE_GETSIZE:
1677 __set_backend_busy(x);
1678 ret = __process_getsize(job);
1679 __post_process(ret, x, job);
1681 case REQUEST_TYPE_GETSIZE_SYNC:
1682 __set_backend_busy(x);
1683 ret = __process_getsize_sync(job);
1685 __free_extra_info(job);
1686 __post_process(ret, x, job);
1688 case REQUEST_TYPE_CLEARDATA:
1689 __set_backend_busy(x);
1690 ret = __process_cleardata(job);
1691 __post_process(ret, x, job);
1693 case REQUEST_TYPE_CLEARCACHE:
1694 __set_backend_busy(x);
1695 ret = __process_clearcache(job);
1696 __post_process(ret, x, job);
1698 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1699 ret = __process_enable_global_app_for_uid(job);
1700 _free_backend_job(job);
1702 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1703 ret = __process_disable_global_app_for_uid(job);
1704 _free_backend_job(job);
1706 case REQUEST_TYPE_KILL:
1707 ret = __process_kill(job);
1708 _free_backend_job(job);
1710 case REQUEST_TYPE_CHECK:
1711 ret = __process_check(job);
1712 _free_backend_job(job);
1714 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1715 ret = __process_generate_license_request(job);
1716 _free_backend_job(job);
1718 case REQUEST_TYPE_REGISTER_LICENSE:
1719 ret = __process_register_license(job);
1720 _free_backend_job(job);
1722 case REQUEST_TYPE_DECRYPT_PACKAGE:
1723 ret = __process_decrypt_package(job);
1724 _free_backend_job(job);
1726 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1727 ret = __process_update_app_splash_screen(job, 1);
1728 _free_backend_job(job);
1730 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1731 ret = __process_update_app_splash_screen(job, 0);
1732 _free_backend_job(job);
1734 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1735 ret = __process_set_restriction_mode(job);
1736 _free_backend_job(job);
1738 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1739 ret = __process_unset_restriction_mode(job);
1740 _free_backend_job(job);
1742 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1743 ret = __process_get_restriction_mode(job);
1744 _free_backend_job(job);
1746 case REQUEST_TYPE_SET_APP_LABEL:
1747 ret = __process_set_app_label(job);
1748 _free_backend_job(job);
1750 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1751 __set_backend_busy(x);
1752 ret = __process_migrate_external_image(job);
1753 __post_process(ret, x, job);
1763 int main(int argc, char *argv[])
1767 DBG("server start");
1769 if (__register_signal_handler()) {
1770 ERR("failed to register signal handler");
1774 r = _init_backend_queue();
1776 ERR("Queue Initialization Failed");
1780 r = __init_backend_info();
1782 ERR("backend info init failed");
1786 r = _init_request_handler();
1788 ERR("dbus init failed");
1792 #if !GLIB_CHECK_VERSION(2, 35, 0)
1795 mainloop = g_main_loop_new(NULL, FALSE);
1797 ERR("g_main_loop_new failed");
1801 DBG("Main loop is created.");
1803 g_main_loop_run(mainloop);
1805 DBG("Quit main loop.");
1806 _fini_request_handler();
1807 __fini_backend_info();
1808 _fini_backend_queue();
1810 g_source_remove(swid);
1811 g_io_channel_unref(sio);
1813 DBG("package manager server terminated.");