4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
29 #include <sys/types.h>
32 #include <sys/types.h>
33 #include <sys/signalfd.h>
42 #include <pkgmgr-info.h>
43 #include <pkgmgr/pkgmgr_parser_db.h>
44 #include <tzplatform_config.h>
45 #include <drm-tizen-apps.h>
46 #ifdef TIZEN_FEATURE_CSR
47 #include <csr-content-screening.h>
50 #include "pkgmgr_installer.h"
51 #include "pkgmgr-server.h"
53 #include "package-manager.h"
56 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
60 #define EXT_STORAGE_GROUP 10001
61 #define EXT_STORAGE_APPDATA_GROUP 10002
62 #define MEDIA_STORAGE_GROUP 10502
63 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
64 #define MAX_LONGLONG_LENGTH 32
79 8 bit value to represent maximum 8 backends.
80 Each bit position corresponds to a queue slot which
81 is dynamically determined.
83 static char backend_busy = 0;
84 extern int num_of_backends;
85 bool is_drm_busy = false;
87 static GIOChannel *sio;
89 static GHashTable *backend_info_table;
90 static GMainLoop *mainloop;
92 static int __check_backend_status_for_exit(void);
93 static int __check_queue_status_for_exit(void);
94 static int __is_backend_busy(int position);
95 static void __set_backend_busy(int position);
96 static void __set_backend_free(int position);
98 gboolean exit_server(void *data);
100 /* To check whether a particular backend is free/busy */
101 static int __is_backend_busy(int position)
103 return backend_busy & (1 << position);
105 /* To set a particular backend as busy */
106 static void __set_backend_busy(int position)
108 backend_busy = backend_busy | (1 << position);
110 /* To set a particular backend as free */
111 static void __set_backend_free(int position)
113 backend_busy = backend_busy & ~(1 << position);
116 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
122 char buf[MAX_LONGLONG_LENGTH];
123 long long result = 0;
124 struct backend_job *job = (struct backend_job *)data;
126 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
127 if (s != G_IO_STATUS_NORMAL) {
128 ERR("getsize fd read failed: %s", err->message);
132 if (strlen(buf) == 0) {
140 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
141 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
143 unlink(job->extra->getsize_fifo);
144 free(job->extra->getsize_fifo);
145 job->extra->getsize_fifo = NULL;
150 static int __setup_size_info_io(struct backend_job *job)
154 job->extra->getsize_fd = open(job->extra->getsize_fifo,
155 O_RDONLY | O_NONBLOCK);
156 if (job->extra->getsize_fd < 0) {
157 ERR("failed to open the fifo(%s), errno(%d)",
158 job->extra->getsize_fifo, errno);
162 job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
163 if (!job->extra->getsize_io)
165 g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
166 g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
167 getsize_wid = g_io_add_watch(job->extra->getsize_io,
168 G_IO_IN, getsize_io_handler, job);
170 ERR("failed to add io watch");
177 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
183 struct signalfd_siginfo fdsi;
184 struct backend_job *job;
188 s = g_io_channel_read_chars(io, (gchar *)&fdsi,
189 sizeof(struct signalfd_siginfo), &len, &err);
190 if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
191 ERR("Signal read failed");
196 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
197 job = (struct backend_job *)g_hash_table_lookup(
198 backend_info_table, (gconstpointer)pid);
200 ERR("Unknown child exit");
204 __set_backend_free(job->backend_slot);
205 if (WIFSIGNALED(status)) {
206 _send_fail_signal(job);
207 INFO("backend[%s][%d] exit with signal[%d]",
208 job->backend_type, pid, WTERMSIG(status));
209 } else if (WEXITSTATUS(status)) {
210 INFO("backend[%s][%d] exit with error",
211 job->backend_type, pid);
213 INFO("backend[%s][%d] exit", job->backend_type, pid);
217 if (job->extra->getsize_fifo) {
218 ERR("invalid backend close");
219 _return_value_to_caller(job->req_id,
220 g_variant_new("(ix)", PKGMGR_R_ERROR,
225 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
227 g_idle_add(queue_job, NULL);
232 static int __init_backend_info(void)
234 backend_info_table = g_hash_table_new_full(g_direct_hash,
235 g_direct_equal, NULL,
236 (GDestroyNotify)_free_backend_job);
241 static void __fini_backend_info(void)
243 /*Free backend info */
244 g_hash_table_destroy(backend_info_table);
247 static int __register_signal_handler(void)
253 sigaddset(&mask, SIGCHLD);
255 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
256 ERR("sigprocmask failed");
260 sfd = signalfd(-1, &mask, SFD_NONBLOCK);
262 ERR("signalfd failed");
266 sio = g_io_channel_unix_new(sfd);
267 g_io_channel_set_close_on_unref(sio, TRUE);
268 g_io_channel_set_encoding(sio, NULL, NULL);
269 g_io_channel_set_buffered(sio, FALSE);
270 swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
272 g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, exit_server, NULL, NULL);
277 static int __check_backend_status_for_exit(void)
280 for (i = 0; i < num_of_backends; i++) {
281 if (__is_backend_busy(i))
287 static int __check_queue_status_for_exit(void)
290 for (i = 0; i < num_of_backends; i++) {
291 if (_is_queue_empty(i) == 0)
297 gboolean exit_server(void *data)
299 DBG("exit_server Start");
300 if (__check_backend_status_for_exit() &&
301 __check_queue_status_for_exit() && !is_drm_busy) {
302 g_main_loop_quit(mainloop);
308 #ifdef TIZEN_FEATURE_CSR
309 static int __check_csr(const char *path)
311 csr_cs_context_h context = NULL;
312 csr_cs_malware_h detected = NULL;
315 ret = csr_cs_context_create(&context);
316 if (ret != CSR_ERROR_NONE) {
317 ERR("Failed to create csr context");
322 ret = csr_cs_scan_file(context, path, &detected);
323 DBG("CSR result[%d]", ret);
325 csr_cs_context_destroy(context);
326 if (detected != NULL) {
327 ERR("CSR Denied[%s] Installation", path);
336 static int __kill_app(char *appid, uid_t uid)
342 is_running = aul_app_is_running_for_uid(appid, uid);
343 /* app is not running */
347 pid = aul_app_get_pid_for_uid(appid, uid);
351 ret = aul_terminate_pid_for_uid(pid, uid);
352 if (ret != AUL_R_OK) {
353 ERR("failed to terminate app(%d)", appid);
360 static int __check_app(char *appid, uid_t uid)
365 is_running = aul_app_is_running_for_uid(appid, uid);
369 pid = aul_app_get_pid_for_uid(appid, uid);
374 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
380 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
382 if (handle == NULL) {
383 perror("appinfo handle is NULL\n");
386 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
388 perror("Failed to get app exec path\n");
391 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
393 perror("Failed to get appid\n");
396 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
398 perror("Failed to get pkgid\n");
402 if (strcmp(pdata->cmd, "kill") == 0) {
403 pdata->pid = __check_app(appid, pdata->uid);
405 ret = __kill_app(appid, pdata->uid);
406 } else if (strcmp(pdata->cmd, "check") == 0) {
407 pdata->pid = __check_app(appid, pdata->uid);
413 void free_user_context(user_ctx *ctx)
420 /* env variable ends by NULL element */
430 int set_environement(user_ctx *ctx)
441 if (ctx->uid != APPFW_UID) {
442 if (setuid(ctx->uid)) {
443 ERR("setuid failed: %d", errno);
447 if (setgid(ctx->gid)) {
448 ERR("setgid failed: %d", errno);
453 n = getgroups(0, NULL);
455 ERR("Failed to get the number of supplementary group IDs");
459 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
460 if (groups == NULL) {
461 ERR("out of memory");
465 n = getgroups(n, groups);
467 ERR("Failed to get list of supplementary group IDs");
472 groups[n++] = EXT_STORAGE_GROUP;
473 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
474 groups[n++] = MEDIA_STORAGE_GROUP;
476 if (setgroups(n, groups) < 0) {
477 ERR("setgroups failed: %d", errno);
484 /* env variable ends by NULL element */
486 if (putenv(env[i]) != 0)
493 user_ctx *get_user_context(uid_t uid)
495 /* we can use getpwnam because this is used only after a
496 * fork and just before an execv
497 * No concurrencial call can corrupt the data
498 * returned by getpwuid
500 user_ctx *context_res;
502 char buf[1024] = {0, };
503 struct passwd pwd, *result;
508 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
509 if (ret != 0 || result == NULL)
513 context_res = (user_ctx *)malloc(sizeof(user_ctx));
518 env = (char **)malloc(3 * sizeof(char *));
523 /* Build environment context */
524 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
525 env[0] = (char *)malloc((len + 1) * sizeof(char));
526 if (env[0] == NULL) {
530 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
531 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
532 env[1] = (char *)malloc((len + 1) * sizeof(char));
533 if (env[1] == NULL) {
537 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
545 /* env variable ends by NULL element */
546 while (env && env[i]) {
553 context_res->env = env;
554 context_res->uid = uid;
555 context_res->gid = pwd.pw_gid;
560 static char **__generate_argv(const char *args)
562 /* Create args vector
563 * req_id + pkgid + args
565 * vector size = # of args +
566 *(req_id + pkgid + NULL termination = 3)
567 * Last value must be NULL for execv.
575 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
576 if (FALSE == ret_parse) {
577 ERR("Failed to split args: %s", args);
578 ERR("messsage: %s", gerr->message);
583 for (i = 0; i < argcp; i++)
584 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
589 void __set_environment(gpointer user_data)
591 user_ctx *ctx = (user_ctx *)user_data;
593 if (set_environement(ctx))
594 ERR("Failed to set env for the user : %d", ctx->uid);
597 static int __fork_and_exec_with_args(char **argv, uid_t uid)
599 user_ctx *user_context;
600 GError *error = NULL;
604 user_context = get_user_context(uid);
606 ERR("Failed to getenv");
610 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
611 __set_environment, (gpointer)user_context, &pid,
614 ERR("Failed to excute backend: %s", error->message);
616 free_user_context(user_context);
620 free_user_context(user_context);
625 static int __change_job_info(struct backend_job *job, uid_t uid,
630 pkgmgrinfo_appinfo_h handle = NULL;
631 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
632 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
633 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
634 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
635 job->req_type != REQUEST_TYPE_ENABLE_APP &&
636 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
637 return PMINFO_R_ERROR;
639 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
640 if (ret != PMINFO_R_OK)
641 return PMINFO_R_ERROR;
643 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
644 if (ret != PMINFO_R_OK)
647 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
649 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
651 ret = PMINFO_R_ERROR;
655 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
656 if (ret != PMINFO_R_OK)
660 job->appid = strdup(job->pkgid);
662 job->pkgid = strdup(pkgid);
665 pkgmgrinfo_appinfo_destroy_appinfo(handle);
670 static int __process_install(struct backend_job *job)
674 char args[MAX_PKG_ARGS_LEN];
679 backend_cmd = job->backend_path;
680 if (backend_cmd == NULL)
683 req_id = g_shell_quote(job->req_id);
684 pkgid = g_shell_quote(job->pkgid);
685 if (!req_id || !pkgid)
688 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
689 req_id, pkgid, (int)job->target_uid, job->args);
691 argv = __generate_argv(args);
693 pid = __fork_and_exec_with_args(argv, APPFW_UID);
701 static int __process_mount_install(struct backend_job *job)
705 char args[MAX_PKG_ARGS_LEN];
710 backend_cmd = job->backend_path;
711 if (backend_cmd == NULL)
714 req_id = g_shell_quote(job->req_id);
715 pkgid = g_shell_quote(job->pkgid);
716 if (!req_id || !pkgid)
719 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
720 req_id, pkgid, (int)job->target_uid, job->args);
722 argv = __generate_argv(args);
724 pid = __fork_and_exec_with_args(argv, APPFW_UID);
732 static int __process_reinstall(struct backend_job *job)
736 char args[MAX_PKG_ARGS_LEN];
741 backend_cmd = job->backend_path;
742 if (backend_cmd == NULL)
745 req_id = g_shell_quote(job->req_id);
746 pkgid = g_shell_quote(job->pkgid);
747 if (!req_id || !pkgid)
750 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
751 req_id, pkgid, (int)job->target_uid);
752 argv = __generate_argv(args);
754 pid = __fork_and_exec_with_args(argv, APPFW_UID);
763 static int __process_uninstall(struct backend_job *job)
767 char args[MAX_PKG_ARGS_LEN];
770 backend_cmd = job->backend_path;
771 if (backend_cmd == NULL)
774 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
775 job->req_id, job->pkgid, (int)job->target_uid);
776 argv = __generate_argv(args);
778 pid = __fork_and_exec_with_args(argv, APPFW_UID);
785 static int __process_move(struct backend_job *job)
789 char args[MAX_PKG_ARGS_LEN];
792 backend_cmd = job->backend_path;
793 if (backend_cmd == NULL)
796 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
797 job->req_id, job->pkgid, (int)job->target_uid, job->args);
798 argv = __generate_argv(args);
800 pid = __fork_and_exec_with_args(argv, APPFW_UID);
807 static int __process_enable_pkg(struct backend_job *job)
811 char args[MAX_PKG_ARGS_LEN];
812 pkgmgrinfo_pkginfo_h pkginfo_h;
818 backend_cmd = job->backend_path;
819 if (backend_cmd == NULL)
822 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
823 job->pkgid, job->target_uid, &pkginfo_h);
824 if (ret != PMINFO_R_OK) {
825 ERR("Failed to get appinfo");
829 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
830 if (ret != PMINFO_R_OK) {
831 ERR("Failed to get global value");
832 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
836 if ((is_global && job->target_uid != GLOBAL_USER) ||
837 (!is_global && job->target_uid == GLOBAL_USER)) {
838 ERR("Invalid attempt to enable pkg");
839 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
843 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
844 if (ret != PMINFO_R_OK) {
845 ERR("Failed to get readonly value");
846 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
850 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
851 backend_cmd, job->req_id, (int)job->target_uid,
852 job->pkgid, (is_readonly) ? "--preload" : "");
853 argv = __generate_argv(args);
854 pid = __fork_and_exec_with_args(argv, APPFW_UID);
857 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
862 static int __process_disable_pkg(struct backend_job *job)
866 char args[MAX_PKG_ARGS_LEN];
867 pkgmgrinfo_pkginfo_h pkginfo_h;
873 backend_cmd = job->backend_path;
874 if (backend_cmd == NULL)
877 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
878 job->pkgid, job->target_uid, &pkginfo_h);
879 if (ret != PMINFO_R_OK) {
880 ERR("Failed to get appinfo");
884 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
885 if (ret != PMINFO_R_OK) {
886 ERR("Failed to get global value");
887 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
891 if ((is_global && job->target_uid != GLOBAL_USER) ||
892 (!is_global && job->target_uid == GLOBAL_USER)) {
893 ERR("Invalid attempt to disable pkg");
894 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
898 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
899 if (ret != PMINFO_R_OK) {
900 ERR("Failed to get readonly value");
901 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
905 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
906 backend_cmd, job->req_id, (int)job->target_uid,
907 job->pkgid, (is_readonly) ? "--preload" : "");
908 argv = __generate_argv(args);
910 pid = __fork_and_exec_with_args(argv, APPFW_UID);
914 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
918 static int __process_register_pkg_update_info(struct backend_job *job)
922 if (!job->extra_data) {
923 _return_value_to_caller(job->req_id,
924 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
928 ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
929 (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
930 if (ret == PMINFO_R_OK)
931 _return_value_to_caller(job->req_id,
932 g_variant_new("(i)", PKGMGR_R_OK));
934 _return_value_to_caller(job->req_id,
935 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
937 pkgmgrinfo_updateinfo_destroy(job->extra_data);
938 job->extra_data = NULL;
943 static int __process_unregister_pkg_update_info(struct backend_job *job)
945 int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
946 (job->pkgid, job->target_uid);
948 if (ret == PMINFO_R_OK)
949 _return_value_to_caller(job->req_id,
950 g_variant_new("(i)", PKGMGR_R_OK));
952 _return_value_to_caller(job->req_id,
953 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
957 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
959 int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
962 if (ret != PMINFO_R_OK) {
963 _return_value_to_caller(job->req_id,
964 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
968 if (__is_admin_user(job->caller_uid)) {
969 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
971 if (ret != PMINFO_R_OK) {
972 _return_value_to_caller(job->req_id,
973 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
977 _return_value_to_caller(job->req_id,
978 g_variant_new("(i)", PKGMGR_R_OK));
983 static int __process_enable_app(struct backend_job *job)
986 bool is_global = false;
988 /* get actual pkgid and replace it to appid which is currently stored
991 ret = __change_job_info(job, job->target_uid, &is_global);
992 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
993 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
994 PKGMGR_INSTALLER_START_KEY_STR,
995 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
997 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
998 PKGMGR_INSTALLER_END_KEY_STR,
999 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1004 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1005 PKGMGR_INSTALLER_START_KEY_STR,
1006 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1008 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1009 job->target_uid, 0);
1010 if (ret != PMINFO_R_OK)
1011 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1012 PKGMGR_INSTALLER_END_KEY_STR,
1013 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1016 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1017 PKGMGR_INSTALLER_END_KEY_STR,
1018 PKGMGR_INSTALLER_OK_EVENT_STR,
1024 static int __process_disable_app(struct backend_job *job)
1027 bool is_global = false;
1029 /* get actual pkgid and replace it to appid which is currently stored
1032 ret = __change_job_info(job, job->target_uid, &is_global);
1033 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1034 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1035 PKGMGR_INSTALLER_START_KEY_STR,
1036 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1038 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1039 PKGMGR_INSTALLER_END_KEY_STR,
1040 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1045 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1046 PKGMGR_INSTALLER_START_KEY_STR,
1047 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1049 ret = __kill_app(job->appid, job->target_uid);
1051 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1052 PKGMGR_INSTALLER_END_KEY_STR,
1053 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1057 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1058 job->target_uid, 1);
1059 if (ret != PMINFO_R_OK)
1060 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1061 PKGMGR_INSTALLER_END_KEY_STR,
1062 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1065 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1066 PKGMGR_INSTALLER_END_KEY_STR,
1067 PKGMGR_INSTALLER_OK_EVENT_STR,
1073 static int __process_enable_global_app_for_uid(struct backend_job *job)
1076 bool is_global = true;
1078 /* get actual pkgid and replace it to appid which is currently stored
1081 ret = __change_job_info(job, job->target_uid, &is_global);
1082 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1083 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1084 PKGMGR_INSTALLER_START_KEY_STR,
1085 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1087 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1088 PKGMGR_INSTALLER_END_KEY_STR,
1089 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1094 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1095 PKGMGR_INSTALLER_START_KEY_STR,
1096 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1099 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1100 job->appid, job->target_uid, 0);
1101 if (ret != PMINFO_R_OK)
1102 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1103 PKGMGR_INSTALLER_END_KEY_STR,
1104 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1107 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1108 PKGMGR_INSTALLER_END_KEY_STR,
1109 PKGMGR_INSTALLER_OK_EVENT_STR,
1115 static int __process_disable_global_app_for_uid(struct backend_job *job)
1118 bool is_global = true;
1120 /* get actual pkgid and replace it to appid which is currently stored
1123 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1124 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1125 _send_app_signal(job->target_uid, job->req_id,
1126 job->pkgid, job->pkgid,
1127 PKGMGR_INSTALLER_START_KEY_STR,
1128 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1130 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1131 PKGMGR_INSTALLER_END_KEY_STR,
1132 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1137 _send_app_signal(job->target_uid, job->req_id,
1138 job->pkgid, job->appid,
1139 PKGMGR_INSTALLER_START_KEY_STR,
1140 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1143 ret = __kill_app(job->appid, job->target_uid);
1144 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1145 job->appid, job->target_uid, 1);
1147 if (ret != PMINFO_R_OK)
1148 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1149 PKGMGR_INSTALLER_END_KEY_STR,
1150 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1153 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1154 PKGMGR_INSTALLER_END_KEY_STR,
1155 PKGMGR_INSTALLER_OK_EVENT_STR,
1161 static int __process_getsize(struct backend_job *job)
1163 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1165 char args[MAX_PKG_ARGS_LEN];
1168 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1169 backend_cmd, job->pkgid, job->args, job->caller_uid,
1170 job->req_id, job->target_uid);
1171 argv = __generate_argv(args);
1172 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1179 static int __process_getsize_sync(struct backend_job *job)
1181 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1183 char args[MAX_PKG_ARGS_LEN];
1184 char fifo_path[PATH_MAX];
1187 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1190 job->extra = calloc(1, sizeof(struct job_extra_info));
1192 ERR("memory alloc failed");
1196 job->extra->getsize_fifo = strdup(fifo_path);
1197 if (!job->extra->getsize_fifo) {
1198 ERR("out of memory");
1202 if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1203 ERR("failed to mkfifo");
1207 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1208 backend_cmd, job->pkgid, job->args, job->caller_uid,
1209 job->req_id, job->target_uid);
1210 argv = __generate_argv(args);
1211 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1216 ERR("failed to execute backend");
1219 if (__setup_size_info_io(job) < 0) {
1220 ERR("failed to setup io handler");
1227 _return_value_to_caller(job->req_id,
1228 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1232 static int __process_cleardata(struct backend_job *job)
1234 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1236 char args[MAX_PKG_ARGS_LEN];
1239 if ((int)job->target_uid < REGULAR_USER)
1242 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1243 backend_cmd, job->pkgid, job->target_uid);
1244 argv = __generate_argv(args);
1245 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1251 static int __process_clearcache(struct backend_job *job)
1253 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1255 char args[MAX_PKG_ARGS_LEN];
1258 if ((int)job->target_uid < REGULAR_USER)
1261 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1262 backend_cmd, job->pkgid, job->target_uid);
1263 argv = __generate_argv(args);
1264 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1270 static int __process_kill(struct backend_job *job)
1273 pkgmgrinfo_pkginfo_h handle;
1276 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1279 ERR("Failed to get handle");
1280 _return_value_to_caller(job->req_id,
1281 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1285 pdata = calloc(1, sizeof(pkgcmd_data));
1286 if (pdata == NULL) {
1287 ERR("memory alloc failed");
1288 _return_value_to_caller(job->req_id,
1289 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1292 pdata->cmd = strdup("kill");
1293 if (pdata->cmd == NULL) {
1294 ERR("out of memory");
1295 _return_value_to_caller(job->req_id,
1296 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1300 pdata->uid = job->target_uid;
1301 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1302 __pkgcmd_app_cb, pdata, job->target_uid);
1304 _return_value_to_caller(job->req_id,
1305 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1309 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1311 ERR("pkgmgrinfo_appinfo_get_list() failed");
1318 static int __process_check(struct backend_job *job)
1321 pkgmgrinfo_pkginfo_h handle;
1324 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1327 ERR("Failed to get handle");
1328 _return_value_to_caller(job->req_id,
1329 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1333 pdata = calloc(1, sizeof(pkgcmd_data));
1334 if (pdata == NULL) {
1335 ERR("memory alloc failed");
1336 _return_value_to_caller(job->req_id,
1337 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1340 pdata->cmd = strdup("check");
1341 if (pdata->cmd == NULL) {
1342 ERR("out of memory");
1343 _return_value_to_caller(job->req_id,
1344 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1348 pdata->uid = job->target_uid;
1349 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1350 __pkgcmd_app_cb, pdata, job->target_uid);
1352 _return_value_to_caller(job->req_id,
1353 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1357 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1359 ERR("pkgmgrinfo_appinfo_get_list() failed");
1366 static int __process_generate_license_request(struct backend_job *job)
1370 char req_data[MAX_PKG_ARGS_LEN];
1371 unsigned int req_data_len;
1372 char license_url[MAX_PKG_ARGS_LEN];
1373 unsigned int license_url_len;
1375 resp_data = job->args;
1376 req_data_len = sizeof(req_data);
1377 license_url_len = sizeof(license_url);
1379 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1380 req_data, &req_data_len, license_url, &license_url_len);
1381 if (ret != TADC_SUCCESS) {
1382 ERR("drm_tizen_generate_license_request failed: %d", ret);
1383 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1384 PKGMGR_R_ESYSTEM, "", ""));
1385 is_drm_busy = false;
1389 _return_value_to_caller(job->req_id,
1390 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1396 static int __process_register_license(struct backend_job *job)
1401 resp_data = job->args;
1403 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1404 if (ret != TADC_SUCCESS) {
1405 ERR("drm_tizen_register_license failed: %d", ret);
1406 _return_value_to_caller(job->req_id,
1407 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1408 is_drm_busy = false;
1412 _return_value_to_caller(job->req_id,
1413 g_variant_new("(i)", PKGMGR_R_OK));
1418 static int __process_decrypt_package(struct backend_job *job)
1421 char *drm_file_path;
1422 char *decrypted_file_path;
1424 drm_file_path = job->pkgid;
1425 decrypted_file_path = job->args;
1427 /* TODO: check ownership of decrypted file */
1428 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1429 decrypted_file_path, strlen(decrypted_file_path));
1430 if (ret != TADC_SUCCESS) {
1431 ERR("drm_tizen_register_license failed: %d", ret);
1432 _return_value_to_caller(job->req_id,
1433 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1434 is_drm_busy = false;
1438 _return_value_to_caller(job->req_id,
1439 g_variant_new("(i)", PKGMGR_R_OK));
1440 is_drm_busy = false;
1445 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1448 bool is_global = false;
1451 ret = __change_job_info(job, job->target_uid, &is_global);
1452 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1455 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1456 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1457 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1458 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1461 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1463 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1464 job->appid, job->target_uid, flag);
1465 if (ret != PMINFO_R_OK)
1466 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1467 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1468 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1471 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1472 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1473 PKGMGR_INSTALLER_OK_EVENT_STR,
1479 static int __process_set_restriction_mode(struct backend_job *job)
1484 mode = atoi(job->args);
1485 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1487 _return_value_to_caller(job->req_id,
1488 g_variant_new("(i)", ret));
1493 static int __process_unset_restriction_mode(struct backend_job *job)
1498 mode = atoi(job->args);
1499 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1501 _return_value_to_caller(job->req_id,
1502 g_variant_new("(i)", ret));
1507 static int __process_get_restriction_mode(struct backend_job *job)
1512 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1514 _return_value_to_caller(job->req_id,
1515 g_variant_new("(ii)", mode, ret));
1520 static int __process_set_app_label(struct backend_job *job)
1524 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1525 job->target_uid, job->args);
1526 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1531 static int __process_migrate_external_image(struct backend_job *job)
1535 char args[MAX_PKG_ARGS_LEN];
1538 backend_cmd = job->backend_path;
1539 if (backend_cmd == NULL)
1542 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1543 backend_cmd, job->req_id, job->pkgid,
1544 (int)job->target_uid, job->args);
1546 argv = __generate_argv(args);
1548 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1554 static int __post_process(int ret, int x, struct backend_job *job)
1557 __set_backend_free(x);
1558 _free_backend_job(job);
1560 g_hash_table_insert(backend_info_table, (gpointer)ret,
1566 gboolean queue_job(void *data)
1568 struct backend_job *job = NULL;
1572 /* Pop a job from queue */
1573 for (x = 0; x < num_of_backends; x++) {
1574 if (__is_backend_busy(x))
1577 job = _pop_queue(x);
1582 /* all backend messages queue are empty or busy */
1583 if (x == num_of_backends || job == NULL) {
1584 DBG("no job available");
1588 /* set current backend job */
1589 DBG("handle request type [%d]", job->req_type);
1591 #ifdef TIZEN_FEATURE_CSR
1592 if (job->req_type == REQUEST_TYPE_INSTALL ||
1593 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1594 job->req_type == REQUEST_TYPE_REINSTALL) {
1595 ret = __check_csr(job->pkgid);
1598 _send_fail_signal(job);
1599 _free_backend_job(job);
1605 switch (job->req_type) {
1606 case REQUEST_TYPE_INSTALL:
1607 __set_backend_busy(x);
1608 ret = __process_install(job);
1609 __post_process(ret, x, job);
1611 case REQUEST_TYPE_MOUNT_INSTALL:
1612 __set_backend_busy(x);
1613 ret = __process_mount_install(job);
1614 __post_process(ret, x, job);
1616 case REQUEST_TYPE_REINSTALL:
1617 __set_backend_busy(x);
1618 ret = __process_reinstall(job);
1619 __post_process(ret, x, job);
1621 case REQUEST_TYPE_UNINSTALL:
1622 __set_backend_busy(x);
1623 ret = __process_uninstall(job);
1624 __post_process(ret, x, job);
1626 case REQUEST_TYPE_MOVE:
1627 __set_backend_busy(x);
1628 ret = __process_move(job);
1629 __post_process(ret, x, job);
1631 case REQUEST_TYPE_ENABLE_PKG:
1632 __set_backend_busy(x);
1633 ret = __process_enable_pkg(job);
1635 _send_fail_signal(job);
1636 __post_process(ret, x, job);
1638 case REQUEST_TYPE_DISABLE_PKG:
1639 __set_backend_busy(x);
1640 ret = __process_disable_pkg(job);
1642 _send_fail_signal(job);
1643 __post_process(ret, x, job);
1645 case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1646 ret = __process_register_pkg_update_info(job);
1647 _free_backend_job(job);
1649 case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1650 ret = __process_unregister_pkg_update_info(job);
1651 _free_backend_job(job);
1653 case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1654 ret = __process_unregister_all_pkg_update_info(job);
1655 _free_backend_job(job);
1657 case REQUEST_TYPE_ENABLE_APP:
1658 ret = __process_enable_app(job);
1659 _free_backend_job(job);
1661 case REQUEST_TYPE_DISABLE_APP:
1662 ret = __process_disable_app(job);
1663 _free_backend_job(job);
1665 case REQUEST_TYPE_GETSIZE:
1666 __set_backend_busy(x);
1667 ret = __process_getsize(job);
1668 __post_process(ret, x, job);
1670 case REQUEST_TYPE_GETSIZE_SYNC:
1671 __set_backend_busy(x);
1672 ret = __process_getsize_sync(job);
1674 __free_extra_info(job);
1675 __post_process(ret, x, job);
1677 case REQUEST_TYPE_CLEARDATA:
1678 __set_backend_busy(x);
1679 ret = __process_cleardata(job);
1680 __post_process(ret, x, job);
1682 case REQUEST_TYPE_CLEARCACHE:
1683 __set_backend_busy(x);
1684 ret = __process_clearcache(job);
1685 __post_process(ret, x, job);
1687 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1688 ret = __process_enable_global_app_for_uid(job);
1689 _free_backend_job(job);
1691 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1692 ret = __process_disable_global_app_for_uid(job);
1693 _free_backend_job(job);
1695 case REQUEST_TYPE_KILL:
1696 ret = __process_kill(job);
1697 _free_backend_job(job);
1699 case REQUEST_TYPE_CHECK:
1700 ret = __process_check(job);
1701 _free_backend_job(job);
1703 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1704 ret = __process_generate_license_request(job);
1705 _free_backend_job(job);
1707 case REQUEST_TYPE_REGISTER_LICENSE:
1708 ret = __process_register_license(job);
1709 _free_backend_job(job);
1711 case REQUEST_TYPE_DECRYPT_PACKAGE:
1712 ret = __process_decrypt_package(job);
1713 _free_backend_job(job);
1715 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1716 ret = __process_update_app_splash_screen(job, 1);
1717 _free_backend_job(job);
1719 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1720 ret = __process_update_app_splash_screen(job, 0);
1721 _free_backend_job(job);
1723 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1724 ret = __process_set_restriction_mode(job);
1725 _free_backend_job(job);
1727 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1728 ret = __process_unset_restriction_mode(job);
1729 _free_backend_job(job);
1731 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1732 ret = __process_get_restriction_mode(job);
1733 _free_backend_job(job);
1735 case REQUEST_TYPE_SET_APP_LABEL:
1736 ret = __process_set_app_label(job);
1737 _free_backend_job(job);
1739 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1740 __set_backend_busy(x);
1741 ret = __process_migrate_external_image(job);
1742 __post_process(ret, x, job);
1752 int main(int argc, char *argv[])
1756 DBG("server start");
1758 if (__register_signal_handler()) {
1759 ERR("failed to register signal handler");
1763 r = _init_backend_queue();
1765 ERR("Queue Initialization Failed");
1769 r = __init_backend_info();
1771 ERR("backend info init failed");
1775 r = _init_request_handler();
1777 ERR("dbus init failed");
1781 #if !GLIB_CHECK_VERSION(2, 35, 0)
1784 mainloop = g_main_loop_new(NULL, FALSE);
1786 ERR("g_main_loop_new failed");
1790 DBG("Main loop is created.");
1792 g_main_loop_run(mainloop);
1794 DBG("Quit main loop.");
1795 _fini_request_handler();
1796 __fini_backend_info();
1797 _fini_backend_queue();
1799 g_source_remove(swid);
1800 g_io_channel_unref(sio);
1802 DBG("package manager server terminated.");