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>
41 #include <pkgmgr-info.h>
42 #include <pkgmgr/pkgmgr_parser_db.h>
43 #include <tzplatform_config.h>
44 #include <drm-tizen-apps.h>
45 #ifdef TIZEN_FEATURE_CSR
46 #include <csr-content-screening.h>
49 #include "pkgmgr_installer.h"
50 #include "pkgmgr-server.h"
52 #include "package-manager.h"
55 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
59 #define EXT_STORAGE_GROUP 10001
60 #define EXT_STORAGE_APPDATA_GROUP 10002
61 #define MEDIA_STORAGE_GROUP 10502
62 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
63 #define MAX_LONGLONG_LENGTH 32
78 8 bit value to represent maximum 8 backends.
79 Each bit position corresponds to a queue slot which
80 is dynamically determined.
82 static char backend_busy = 0;
83 extern int num_of_backends;
85 struct signal_info_t {
90 static int pipe_sig[2];
91 static GIOChannel *pipe_io;
92 static guint pipe_wid;
93 static GHashTable *backend_info_table;
94 static GMainLoop *mainloop;
96 static int __check_backend_status_for_exit(void);
97 static int __check_queue_status_for_exit(void);
98 static int __is_backend_busy(int position);
99 static void __set_backend_busy(int position);
100 static void __set_backend_free(int position);
101 static void sighandler(int signo);
103 gboolean exit_server(void *data);
105 /* To check whether a particular backend is free/busy */
106 static int __is_backend_busy(int position)
108 return backend_busy & (1 << position);
110 /* To set a particular backend as busy */
111 static void __set_backend_busy(int position)
113 backend_busy = backend_busy | (1 << position);
115 /* To set a particular backend as free */
116 static void __set_backend_free(int position)
118 backend_busy = backend_busy & ~(1 << position);
121 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
127 char buf[MAX_LONGLONG_LENGTH];
128 long long result = 0;
129 struct backend_job *job = (struct backend_job *)data;
131 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
132 if (s != G_IO_STATUS_NORMAL) {
133 ERR("getsize fd read failed: %s", err->message);
137 if (strlen(buf) == 0) {
145 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
146 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
148 unlink(job->extra->getsize_fifo);
149 free(job->extra->getsize_fifo);
150 job->extra->getsize_fifo = NULL;
155 static int __setup_size_info_io(struct backend_job *job)
159 job->extra->getsize_fd = open(job->extra->getsize_fifo,
160 O_RDONLY | O_NONBLOCK);
161 if (job->extra->getsize_fd < 0) {
162 ERR("failed to open the fifo(%s), errno(%d)",
163 job->extra->getsize_fifo, errno);
167 job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
168 if (!job->extra->getsize_io)
170 g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
171 g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
172 getsize_wid = g_io_add_watch(job->extra->getsize_io,
173 G_IO_IN, getsize_io_handler, job);
175 ERR("failed to add io watch");
182 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond,
188 struct signal_info_t info;
189 struct backend_job *job;
191 s = g_io_channel_read_chars(io, (gchar *)&info,
192 sizeof(struct signal_info_t), &len, &err);
193 if (s != G_IO_STATUS_NORMAL) {
194 ERR("Signal pipe read failed: %s", err->message);
199 job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
200 (gconstpointer)info.pid);
202 ERR("Unknown child exit");
206 __set_backend_free(job->backend_slot);
207 if (WIFSIGNALED(info.status)) {
208 _send_fail_signal(job);
209 DBG("backend[%s] exit with signal[%d]", job->backend_type,
210 WTERMSIG(info.status));
211 } else if (WEXITSTATUS(info.status)) {
212 DBG("backend[%s] exit with error", job->backend_type);
214 DBG("backend[%s] exit", job->backend_type);
218 if (job->extra->getsize_fifo) {
219 ERR("invalid backend close");
220 _return_value_to_caller(job->req_id,
221 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
225 g_hash_table_remove(backend_info_table, (gconstpointer)info.pid);
226 g_idle_add(queue_job, NULL);
231 static int __init_backend_info(void)
233 backend_info_table = g_hash_table_new_full(g_direct_hash,
234 g_direct_equal, NULL,
235 (GDestroyNotify)_free_backend_job);
237 if (pipe(pipe_sig)) {
238 ERR("create pipe failed");
242 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
243 g_io_channel_set_encoding(pipe_io, NULL, NULL);
244 g_io_channel_set_buffered(pipe_io, FALSE);
245 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
250 static void __fini_backend_info(void)
252 g_source_remove(pipe_wid);
253 g_io_channel_unref(pipe_io);
257 /*Free backend info */
258 g_hash_table_destroy(backend_info_table);
261 static void sighandler(int signo)
263 struct signal_info_t info;
264 char buf[1024] = {0, };
266 info.pid = waitpid(-1, &info.status, WNOHANG);
267 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
268 ERR("failed to write result: %s",
269 strerror_r(errno, buf, sizeof(buf)));
272 static int __register_signal_handler(void)
274 static int sig_reg = 0;
275 struct sigaction act;
280 act.sa_handler = sighandler;
281 sigemptyset(&act.sa_mask);
282 act.sa_flags = SA_NOCLDSTOP;
283 if (sigaction(SIGCHLD, &act, NULL) < 0) {
284 ERR("signal: SIGCHLD failed");
288 g_timeout_add_seconds(2, exit_server, NULL);
294 static int __check_backend_status_for_exit(void)
297 for (i = 0; i < num_of_backends; i++) {
298 if (__is_backend_busy(i))
304 static int __check_queue_status_for_exit(void)
307 for (i = 0; i < num_of_backends; i++) {
308 if (_is_queue_empty(i) == 0)
314 gboolean exit_server(void *data)
316 DBG("exit_server Start");
317 if (__check_backend_status_for_exit() &&
318 __check_queue_status_for_exit()) {
319 g_main_loop_quit(mainloop);
325 #ifdef TIZEN_FEATURE_CSR
326 static int __check_csr(const char *path)
328 csr_cs_context_h context = NULL;
329 csr_cs_malware_h detected = NULL;
332 ret = csr_cs_context_create(&context);
333 if (ret != CSR_ERROR_NONE) {
334 ERR("Failed to create csr context");
339 ret = csr_cs_scan_file(context, path, &detected);
340 DBG("CSR result[%d]", ret);
342 csr_cs_context_destroy(context);
343 if (detected != NULL) {
344 ERR("CSR Denied[%s] Installation", path);
353 static int __kill_app(char *appid, uid_t uid)
359 is_running = aul_app_is_running_for_uid(appid, uid);
360 /* app is not running */
364 pid = aul_app_get_pid_for_uid(appid, uid);
368 ret = aul_terminate_pid_for_uid(pid, uid);
369 if (ret != AUL_R_OK) {
370 ERR("failed to terminate app(%d)", appid);
377 static int __check_app(char *appid, uid_t uid)
382 is_running = aul_app_is_running_for_uid(appid, uid);
386 pid = aul_app_get_pid_for_uid(appid, uid);
391 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
397 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
399 if (handle == NULL) {
400 perror("appinfo handle is NULL\n");
403 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
405 perror("Failed to get app exec path\n");
408 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
410 perror("Failed to get appid\n");
413 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
415 perror("Failed to get pkgid\n");
419 if (strcmp(pdata->cmd, "kill") == 0) {
420 pdata->pid = __check_app(appid, pdata->uid);
422 ret = __kill_app(appid, pdata->uid);
423 } else if (strcmp(pdata->cmd, "check") == 0) {
424 pdata->pid = __check_app(appid, pdata->uid);
430 void free_user_context(user_ctx *ctx)
437 /* env variable ends by NULL element */
447 int set_environement(user_ctx *ctx)
458 if (ctx->uid != APPFW_UID) {
459 if (setuid(ctx->uid)) {
460 ERR("setuid failed: %d", errno);
464 if (setgid(ctx->gid)) {
465 ERR("setgid failed: %d", errno);
470 n = getgroups(0, NULL);
472 ERR("Failed to get the number of supplementary group IDs");
476 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
477 if (groups == NULL) {
478 ERR("out of memory");
482 n = getgroups(n, groups);
484 ERR("Failed to get list of supplementary group IDs");
489 groups[n++] = EXT_STORAGE_GROUP;
490 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
491 groups[n++] = MEDIA_STORAGE_GROUP;
493 if (setgroups(n, groups) < 0) {
494 ERR("setgroups failed: %d", errno);
501 /* env variable ends by NULL element */
503 if (putenv(env[i]) != 0)
510 user_ctx *get_user_context(uid_t uid)
512 /* we can use getpwnam because this is used only after a
513 * fork and just before an execv
514 * No concurrencial call can corrupt the data
515 * returned by getpwuid
517 user_ctx *context_res;
519 char buf[1024] = {0, };
520 struct passwd pwd, *result;
525 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
526 if (ret != 0 || result == NULL)
530 context_res = (user_ctx *)malloc(sizeof(user_ctx));
535 env = (char **)malloc(3 * sizeof(char *));
540 /* Build environment context */
541 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
542 env[0] = (char *)malloc((len + 1) * sizeof(char));
543 if (env[0] == NULL) {
547 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
548 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
549 env[1] = (char *)malloc((len + 1) * sizeof(char));
550 if (env[1] == NULL) {
554 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
562 /* env variable ends by NULL element */
563 while (env && env[i]) {
570 context_res->env = env;
571 context_res->uid = uid;
572 context_res->gid = pwd.pw_gid;
577 static char **__generate_argv(const char *args)
579 /* Create args vector
580 * req_id + pkgid + args
582 * vector size = # of args +
583 *(req_id + pkgid + NULL termination = 3)
584 * Last value must be NULL for execv.
592 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
593 if (FALSE == ret_parse) {
594 DBG("Failed to split args: %s", args);
595 DBG("messsage: %s", gerr->message);
600 for (i = 0; i < argcp; i++)
601 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
606 void __set_environment(gpointer user_data)
608 user_ctx *ctx = (user_ctx *)user_data;
610 if (set_environement(ctx))
611 DBG("Failed to set env for the user : %d", ctx->uid);
614 static int __fork_and_exec_with_args(char **argv, uid_t uid)
616 user_ctx *user_context;
617 GError *error = NULL;
621 user_context = get_user_context(uid);
623 DBG("Failed to getenv");
627 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
628 __set_environment, (gpointer)user_context, &pid,
631 ERR("Failed to excute backend: %s", error->message);
633 free_user_context(user_context);
637 free_user_context(user_context);
642 static int __change_job_info(struct backend_job *job, uid_t uid,
647 pkgmgrinfo_appinfo_h handle = NULL;
648 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
649 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
650 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
651 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
652 job->req_type != REQUEST_TYPE_ENABLE_APP &&
653 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
654 return PMINFO_R_ERROR;
656 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
657 if (ret != PMINFO_R_OK)
658 return PMINFO_R_ERROR;
660 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
661 if (ret != PMINFO_R_OK)
664 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
666 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
668 ret = PMINFO_R_ERROR;
672 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
673 if (ret != PMINFO_R_OK)
677 job->appid = strdup(job->pkgid);
679 job->pkgid = strdup(pkgid);
682 pkgmgrinfo_appinfo_destroy_appinfo(handle);
687 static int __process_install(struct backend_job *job)
691 char args[MAX_PKG_ARGS_LEN];
696 backend_cmd = job->backend_path;
697 if (backend_cmd == NULL)
700 req_id = g_shell_quote(job->req_id);
701 pkgid = g_shell_quote(job->pkgid);
702 if (!req_id || !pkgid)
705 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
706 req_id, pkgid, (int)job->target_uid, job->args);
708 argv = __generate_argv(args);
710 pid = __fork_and_exec_with_args(argv, APPFW_UID);
718 static int __process_mount_install(struct backend_job *job)
722 char args[MAX_PKG_ARGS_LEN];
727 backend_cmd = job->backend_path;
728 if (backend_cmd == NULL)
731 req_id = g_shell_quote(job->req_id);
732 pkgid = g_shell_quote(job->pkgid);
733 if (!req_id || !pkgid)
736 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
737 req_id, pkgid, (int)job->target_uid, job->args);
739 argv = __generate_argv(args);
741 pid = __fork_and_exec_with_args(argv, APPFW_UID);
749 static int __process_reinstall(struct backend_job *job)
753 char args[MAX_PKG_ARGS_LEN];
758 backend_cmd = job->backend_path;
759 if (backend_cmd == NULL)
762 req_id = g_shell_quote(job->req_id);
763 pkgid = g_shell_quote(job->pkgid);
764 if (!req_id || !pkgid)
767 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
768 req_id, pkgid, (int)job->target_uid);
769 argv = __generate_argv(args);
771 pid = __fork_and_exec_with_args(argv, APPFW_UID);
780 static int __process_uninstall(struct backend_job *job)
784 char args[MAX_PKG_ARGS_LEN];
787 backend_cmd = job->backend_path;
788 if (backend_cmd == NULL)
791 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
792 job->req_id, job->pkgid, (int)job->target_uid);
793 argv = __generate_argv(args);
795 pid = __fork_and_exec_with_args(argv, APPFW_UID);
802 static int __process_move(struct backend_job *job)
806 char args[MAX_PKG_ARGS_LEN];
809 backend_cmd = job->backend_path;
810 if (backend_cmd == NULL)
813 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
814 job->req_id, job->pkgid, (int)job->target_uid, job->args);
815 argv = __generate_argv(args);
817 pid = __fork_and_exec_with_args(argv, APPFW_UID);
824 static int __process_enable_pkg(struct backend_job *job)
828 char args[MAX_PKG_ARGS_LEN];
829 pkgmgrinfo_pkginfo_h pkginfo_h;
835 backend_cmd = job->backend_path;
836 if (backend_cmd == NULL)
839 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
840 job->pkgid, job->target_uid, &pkginfo_h);
841 if (ret != PMINFO_R_OK) {
842 ERR("Failed to get appinfo");
846 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
847 if (ret != PMINFO_R_OK) {
848 ERR("Failed to get global value");
849 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
853 if ((is_global && job->target_uid != GLOBAL_USER) ||
854 (!is_global && job->target_uid == GLOBAL_USER)) {
855 ERR("Invalid attempt to enable pkg");
856 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
860 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
861 if (ret != PMINFO_R_OK) {
862 ERR("Failed to get readonly value");
863 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
867 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
868 backend_cmd, job->req_id, (int)job->target_uid,
869 job->pkgid, (is_readonly) ? "--preload" : "");
870 argv = __generate_argv(args);
871 pid = __fork_and_exec_with_args(argv, APPFW_UID);
874 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
879 static int __process_disable_pkg(struct backend_job *job)
883 char args[MAX_PKG_ARGS_LEN];
884 pkgmgrinfo_pkginfo_h pkginfo_h;
890 backend_cmd = job->backend_path;
891 if (backend_cmd == NULL)
894 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
895 job->pkgid, job->target_uid, &pkginfo_h);
896 if (ret != PMINFO_R_OK) {
897 ERR("Failed to get appinfo");
901 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
902 if (ret != PMINFO_R_OK) {
903 ERR("Failed to get global value");
904 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
908 if ((is_global && job->target_uid != GLOBAL_USER) ||
909 (!is_global && job->target_uid == GLOBAL_USER)) {
910 ERR("Invalid attempt to disable pkg");
911 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
915 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
916 if (ret != PMINFO_R_OK) {
917 ERR("Failed to get readonly value");
918 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
922 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
923 backend_cmd, job->req_id, (int)job->target_uid,
924 job->pkgid, (is_readonly) ? "--preload" : "");
925 argv = __generate_argv(args);
927 pid = __fork_and_exec_with_args(argv, APPFW_UID);
931 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
935 static int __process_enable_app(struct backend_job *job)
938 bool is_global = false;
940 /* get actual pkgid and replace it to appid which is currently stored
943 ret = __change_job_info(job, job->target_uid, &is_global);
944 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
945 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
946 PKGMGR_INSTALLER_START_KEY_STR,
947 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
949 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
950 PKGMGR_INSTALLER_END_KEY_STR,
951 PKGMGR_INSTALLER_FAIL_EVENT_STR,
956 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
957 PKGMGR_INSTALLER_START_KEY_STR,
958 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
960 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
962 if (ret != PMINFO_R_OK)
963 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
964 PKGMGR_INSTALLER_END_KEY_STR,
965 PKGMGR_INSTALLER_FAIL_EVENT_STR,
968 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
969 PKGMGR_INSTALLER_END_KEY_STR,
970 PKGMGR_INSTALLER_OK_EVENT_STR,
976 static int __process_disable_app(struct backend_job *job)
979 bool is_global = false;
981 /* get actual pkgid and replace it to appid which is currently stored
984 ret = __change_job_info(job, job->target_uid, &is_global);
985 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
986 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
987 PKGMGR_INSTALLER_START_KEY_STR,
988 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
990 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
991 PKGMGR_INSTALLER_END_KEY_STR,
992 PKGMGR_INSTALLER_FAIL_EVENT_STR,
997 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
998 PKGMGR_INSTALLER_START_KEY_STR,
999 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1001 ret = __kill_app(job->appid, job->target_uid);
1003 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1004 PKGMGR_INSTALLER_END_KEY_STR,
1005 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1009 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1010 job->target_uid, 1);
1011 if (ret != PMINFO_R_OK)
1012 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1013 PKGMGR_INSTALLER_END_KEY_STR,
1014 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1017 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1018 PKGMGR_INSTALLER_END_KEY_STR,
1019 PKGMGR_INSTALLER_OK_EVENT_STR,
1025 static int __process_enable_global_app_for_uid(struct backend_job *job)
1028 bool is_global = true;
1030 /* get actual pkgid and replace it to appid which is currently stored
1033 ret = __change_job_info(job, job->target_uid, &is_global);
1034 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1035 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1036 PKGMGR_INSTALLER_START_KEY_STR,
1037 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1039 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1040 PKGMGR_INSTALLER_END_KEY_STR,
1041 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1046 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1047 PKGMGR_INSTALLER_START_KEY_STR,
1048 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1051 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1052 job->appid, job->target_uid, 0);
1053 if (ret != PMINFO_R_OK)
1054 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1055 PKGMGR_INSTALLER_END_KEY_STR,
1056 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1059 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1060 PKGMGR_INSTALLER_END_KEY_STR,
1061 PKGMGR_INSTALLER_OK_EVENT_STR,
1067 static int __process_disable_global_app_for_uid(struct backend_job *job)
1070 bool is_global = true;
1072 /* get actual pkgid and replace it to appid which is currently stored
1075 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1076 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1077 _send_app_signal(job->target_uid, job->req_id,
1078 job->pkgid, job->pkgid,
1079 PKGMGR_INSTALLER_START_KEY_STR,
1080 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1082 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1083 PKGMGR_INSTALLER_END_KEY_STR,
1084 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1089 _send_app_signal(job->target_uid, job->req_id,
1090 job->pkgid, job->appid,
1091 PKGMGR_INSTALLER_START_KEY_STR,
1092 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1095 ret = __kill_app(job->appid, job->target_uid);
1096 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1097 job->appid, job->target_uid, 1);
1099 if (ret != PMINFO_R_OK)
1100 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1101 PKGMGR_INSTALLER_END_KEY_STR,
1102 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1105 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1106 PKGMGR_INSTALLER_END_KEY_STR,
1107 PKGMGR_INSTALLER_OK_EVENT_STR,
1113 static int __process_getsize(struct backend_job *job)
1115 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1117 char args[MAX_PKG_ARGS_LEN];
1120 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1121 backend_cmd, job->pkgid, job->args, job->caller_uid,
1122 job->req_id, job->target_uid);
1123 argv = __generate_argv(args);
1124 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1131 static int __process_getsize_sync(struct backend_job *job)
1133 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1135 char args[MAX_PKG_ARGS_LEN];
1136 char fifo_path[PATH_MAX];
1139 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1142 job->extra = calloc(1, sizeof(struct job_extra_info));
1144 ERR("memory alloc failed");
1148 job->extra->getsize_fifo = strdup(fifo_path);
1149 if (!job->extra->getsize_fifo) {
1150 ERR("out of memory");
1154 if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1155 ERR("failed to mkfifo");
1159 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1160 backend_cmd, job->pkgid, job->args, job->caller_uid,
1161 job->req_id, job->target_uid);
1162 argv = __generate_argv(args);
1163 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1168 ERR("failed to execute backend");
1171 if (__setup_size_info_io(job) < 0) {
1172 ERR("failed to setup io handler");
1179 _return_value_to_caller(job->req_id,
1180 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1184 static int __process_cleardata(struct backend_job *job)
1186 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1188 char args[MAX_PKG_ARGS_LEN];
1191 if ((int)job->target_uid < REGULAR_USER)
1194 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1195 backend_cmd, job->pkgid, job->target_uid);
1196 argv = __generate_argv(args);
1197 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1203 static int __process_clearcache(struct backend_job *job)
1205 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1207 char args[MAX_PKG_ARGS_LEN];
1210 if ((int)job->target_uid < REGULAR_USER)
1213 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1214 backend_cmd, job->pkgid, job->target_uid);
1215 argv = __generate_argv(args);
1216 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1222 static int __process_kill(struct backend_job *job)
1225 pkgmgrinfo_pkginfo_h handle;
1228 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1231 ERR("Failed to get handle");
1232 _return_value_to_caller(job->req_id,
1233 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1237 pdata = calloc(1, sizeof(pkgcmd_data));
1238 if (pdata == NULL) {
1239 ERR("memory alloc failed");
1240 _return_value_to_caller(job->req_id,
1241 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1244 pdata->cmd = strdup("kill");
1245 if (pdata->cmd == NULL) {
1246 ERR("out of memory");
1247 _return_value_to_caller(job->req_id,
1248 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1252 pdata->uid = job->target_uid;
1253 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1254 __pkgcmd_app_cb, pdata, job->target_uid);
1256 _return_value_to_caller(job->req_id,
1257 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1261 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1263 ERR("pkgmgrinfo_appinfo_get_list() failed");
1270 static int __process_check(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("check");
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_generate_license_request(struct backend_job *job)
1322 char req_data[MAX_PKG_ARGS_LEN];
1323 unsigned int req_data_len;
1324 char license_url[MAX_PKG_ARGS_LEN];
1325 unsigned int license_url_len;
1327 resp_data = job->args;
1328 req_data_len = sizeof(req_data);
1329 license_url_len = sizeof(license_url);
1331 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1332 req_data, &req_data_len, license_url, &license_url_len);
1333 if (ret != TADC_SUCCESS) {
1334 ERR("drm_tizen_generate_license_request failed: %d", ret);
1335 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1336 PKGMGR_R_ESYSTEM, "", ""));
1340 _return_value_to_caller(job->req_id,
1341 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1347 static int __process_register_license(struct backend_job *job)
1352 resp_data = job->args;
1354 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1355 if (ret != TADC_SUCCESS) {
1356 ERR("drm_tizen_register_license failed: %d", ret);
1357 _return_value_to_caller(job->req_id,
1358 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1362 _return_value_to_caller(job->req_id,
1363 g_variant_new("(i)", PKGMGR_R_OK));
1368 static int __process_decrypt_package(struct backend_job *job)
1371 char *drm_file_path;
1372 char *decrypted_file_path;
1374 drm_file_path = job->pkgid;
1375 decrypted_file_path = job->args;
1377 /* TODO: check ownership of decrypted file */
1378 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1379 decrypted_file_path, strlen(decrypted_file_path));
1380 if (ret != TADC_SUCCESS) {
1381 ERR("drm_tizen_register_license failed: %d", ret);
1382 _return_value_to_caller(job->req_id,
1383 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1387 _return_value_to_caller(job->req_id,
1388 g_variant_new("(i)", PKGMGR_R_OK));
1393 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1396 bool is_global = false;
1399 ret = __change_job_info(job, job->target_uid, &is_global);
1400 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1403 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1404 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1405 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1406 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1409 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1411 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1412 job->appid, job->target_uid, flag);
1413 if (ret != PMINFO_R_OK)
1414 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1415 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1416 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1419 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1420 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1421 PKGMGR_INSTALLER_OK_EVENT_STR,
1427 static int __process_set_restriction_mode(struct backend_job *job)
1432 mode = atoi(job->args);
1433 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1435 _return_value_to_caller(job->req_id,
1436 g_variant_new("(i)", ret));
1441 static int __process_unset_restriction_mode(struct backend_job *job)
1446 mode = atoi(job->args);
1447 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1449 _return_value_to_caller(job->req_id,
1450 g_variant_new("(i)", ret));
1455 static int __process_get_restriction_mode(struct backend_job *job)
1460 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1462 _return_value_to_caller(job->req_id,
1463 g_variant_new("(ii)", mode, ret));
1468 static int __process_set_app_label(struct backend_job *job)
1472 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1473 job->target_uid, job->args);
1474 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1479 static int __process_migrate_external_image(struct backend_job *job)
1483 char args[MAX_PKG_ARGS_LEN];
1486 backend_cmd = job->backend_path;
1487 if (backend_cmd == NULL)
1490 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1491 backend_cmd, job->req_id, job->pkgid,
1492 (int)job->target_uid, job->args);
1494 argv = __generate_argv(args);
1496 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1502 static int __post_process(int ret, int x, struct backend_job *job)
1505 __set_backend_free(x);
1506 _free_backend_job(job);
1508 g_hash_table_insert(backend_info_table, (gpointer)ret,
1514 gboolean queue_job(void *data)
1516 struct backend_job *job = NULL;
1520 /* Pop a job from queue */
1521 for (x = 0; x < num_of_backends; x++) {
1522 if (__is_backend_busy(x))
1525 job = _pop_queue(x);
1530 /* all backend messages queue are empty or busy */
1531 if (x == num_of_backends || job == NULL) {
1532 DBG("no job available");
1536 /* set current backend job */
1537 DBG("handle request type [%d]", job->req_type);
1539 #ifdef TIZEN_FEATURE_CSR
1540 if (job->req_type == REQUEST_TYPE_INSTALL ||
1541 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1542 job->req_type == REQUEST_TYPE_REINSTALL) {
1543 ret = __check_csr(job->pkgid);
1546 _send_fail_signal(job);
1547 _free_backend_job(job);
1553 switch (job->req_type) {
1554 case REQUEST_TYPE_INSTALL:
1555 __set_backend_busy(x);
1556 ret = __process_install(job);
1557 __post_process(ret, x, job);
1559 case REQUEST_TYPE_MOUNT_INSTALL:
1560 __set_backend_busy(x);
1561 ret = __process_mount_install(job);
1562 __post_process(ret, x, job);
1564 case REQUEST_TYPE_REINSTALL:
1565 __set_backend_busy(x);
1566 ret = __process_reinstall(job);
1567 __post_process(ret, x, job);
1569 case REQUEST_TYPE_UNINSTALL:
1570 __set_backend_busy(x);
1571 ret = __process_uninstall(job);
1572 __post_process(ret, x, job);
1574 case REQUEST_TYPE_MOVE:
1575 __set_backend_busy(x);
1576 ret = __process_move(job);
1577 __post_process(ret, x, job);
1579 case REQUEST_TYPE_ENABLE_PKG:
1580 __set_backend_busy(x);
1581 ret = __process_enable_pkg(job);
1583 _send_fail_signal(job);
1584 __post_process(ret, x, job);
1586 case REQUEST_TYPE_DISABLE_PKG:
1587 __set_backend_busy(x);
1588 ret = __process_disable_pkg(job);
1590 _send_fail_signal(job);
1591 __post_process(ret, x, job);
1593 case REQUEST_TYPE_ENABLE_APP:
1594 ret = __process_enable_app(job);
1595 _free_backend_job(job);
1597 case REQUEST_TYPE_DISABLE_APP:
1598 ret = __process_disable_app(job);
1599 _free_backend_job(job);
1601 case REQUEST_TYPE_GETSIZE:
1602 __set_backend_busy(x);
1603 ret = __process_getsize(job);
1604 __post_process(ret, x, job);
1606 case REQUEST_TYPE_GETSIZE_SYNC:
1607 __set_backend_busy(x);
1608 ret = __process_getsize_sync(job);
1610 __free_extra_info(job);
1611 __post_process(ret, x, job);
1613 case REQUEST_TYPE_CLEARDATA:
1614 __set_backend_busy(x);
1615 ret = __process_cleardata(job);
1616 __post_process(ret, x, job);
1618 case REQUEST_TYPE_CLEARCACHE:
1619 __set_backend_busy(x);
1620 ret = __process_clearcache(job);
1621 __post_process(ret, x, job);
1623 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1624 ret = __process_enable_global_app_for_uid(job);
1625 _free_backend_job(job);
1627 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1628 ret = __process_disable_global_app_for_uid(job);
1629 _free_backend_job(job);
1631 case REQUEST_TYPE_KILL:
1632 ret = __process_kill(job);
1633 _free_backend_job(job);
1635 case REQUEST_TYPE_CHECK:
1636 ret = __process_check(job);
1637 _free_backend_job(job);
1639 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1640 ret = __process_generate_license_request(job);
1641 _free_backend_job(job);
1643 case REQUEST_TYPE_REGISTER_LICENSE:
1644 ret = __process_register_license(job);
1645 _free_backend_job(job);
1647 case REQUEST_TYPE_DECRYPT_PACKAGE:
1648 ret = __process_decrypt_package(job);
1649 _free_backend_job(job);
1651 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1652 ret = __process_update_app_splash_screen(job, 1);
1653 _free_backend_job(job);
1655 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1656 ret = __process_update_app_splash_screen(job, 0);
1657 _free_backend_job(job);
1659 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1660 ret = __process_set_restriction_mode(job);
1661 _free_backend_job(job);
1663 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1664 ret = __process_unset_restriction_mode(job);
1665 _free_backend_job(job);
1667 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1668 ret = __process_get_restriction_mode(job);
1669 _free_backend_job(job);
1671 case REQUEST_TYPE_SET_APP_LABEL:
1672 ret = __process_set_app_label(job);
1673 _free_backend_job(job);
1675 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1676 __set_backend_busy(x);
1677 ret = __process_migrate_external_image(job);
1678 __post_process(ret, x, job);
1688 int main(int argc, char *argv[])
1692 DBG("server start");
1694 r = _init_backend_queue();
1696 DBG("Queue Initialization Failed");
1700 r = __init_backend_info();
1702 DBG("backend info init failed");
1706 r = _init_request_handler();
1708 ERR("dbus init failed");
1712 if (__register_signal_handler()) {
1713 ERR("failed to register signal handler");
1717 #if !GLIB_CHECK_VERSION(2, 35, 0)
1720 mainloop = g_main_loop_new(NULL, FALSE);
1722 ERR("g_main_loop_new failed");
1726 DBG("Main loop is created.");
1728 g_main_loop_run(mainloop);
1730 DBG("Quit main loop.");
1731 _fini_request_handler();
1732 __fini_backend_info();
1733 _fini_backend_queue();
1735 DBG("package manager server terminated.");