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 #include <csr-content-screening.h>
47 #include "pkgmgr_installer.h"
48 #include "pkgmgr-server.h"
50 #include "package-manager.h"
52 #include <system_info.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);
106 TIZEN_PROFILE_UNKNOWN = 0,
107 TIZEN_PROFILE_MOBILE = 0x1,
108 TIZEN_PROFILE_WEARABLE = 0x2,
109 TIZEN_PROFILE_TV = 0x4,
110 TIZEN_PROFILE_IVI = 0x8,
111 TIZEN_PROFILE_COMMON = 0x10,
114 static tizen_profile_t _get_tizen_profile()
116 static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
119 if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
122 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
123 switch (*profileName) {
126 profile = TIZEN_PROFILE_MOBILE;
130 profile = TIZEN_PROFILE_WEARABLE;
134 profile = TIZEN_PROFILE_TV;
138 profile = TIZEN_PROFILE_IVI;
140 default: // common or unknown ==> ALL ARE COMMON.
141 profile = TIZEN_PROFILE_COMMON;
147 #define TIZEN_FEATURE_CSR (_get_tizen_profile() != TIZEN_PROFILE_TV)
149 /* To check whether a particular backend is free/busy */
150 static int __is_backend_busy(int position)
152 return backend_busy & (1 << position);
154 /* To set a particular backend as busy */
155 static void __set_backend_busy(int position)
157 backend_busy = backend_busy | (1 << position);
159 /* To set a particular backend as free */
160 static void __set_backend_free(int position)
162 backend_busy = backend_busy & ~(1 << position);
165 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
171 char buf[MAX_LONGLONG_LENGTH];
172 long long result = 0;
173 struct backend_job *job = (struct backend_job *)data;
175 s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
176 if (s != G_IO_STATUS_NORMAL) {
177 ERR("getsize fd read failed: %s", err->message);
181 if (strlen(buf) == 0) {
189 _return_value_to_caller(job->req_id, g_variant_new("(ix)",
190 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
192 unlink(job->extra->getsize_fifo);
193 free(job->extra->getsize_fifo);
194 job->extra->getsize_fifo = NULL;
199 static int __setup_size_info_io(struct backend_job *job)
203 job->extra->getsize_fd = open(job->extra->getsize_fifo,
204 O_RDONLY | O_NONBLOCK);
205 if (job->extra->getsize_fd < 0) {
206 ERR("failed to open the fifo(%s), errno(%d)",
207 job->extra->getsize_fifo, errno);
211 job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd);
212 if (!job->extra->getsize_io)
214 g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL);
215 g_io_channel_set_buffered(job->extra->getsize_io, FALSE);
216 getsize_wid = g_io_add_watch(job->extra->getsize_io,
217 G_IO_IN, getsize_io_handler, job);
219 ERR("failed to add io watch");
226 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond,
232 struct signal_info_t info;
233 struct backend_job *job;
235 s = g_io_channel_read_chars(io, (gchar *)&info,
236 sizeof(struct signal_info_t), &len, &err);
237 if (s != G_IO_STATUS_NORMAL) {
238 ERR("Signal pipe read failed: %s", err->message);
243 job = (struct backend_job *)g_hash_table_lookup(backend_info_table,
244 (gconstpointer)info.pid);
246 ERR("Unknown child exit");
250 __set_backend_free(job->backend_slot);
251 if (WIFSIGNALED(info.status)) {
252 _send_fail_signal(job);
253 DBG("backend[%s] exit with signal[%d]", job->backend_type,
254 WTERMSIG(info.status));
255 } else if (WEXITSTATUS(info.status)) {
256 DBG("backend[%s] exit with error", job->backend_type);
258 DBG("backend[%s] exit", job->backend_type);
262 if (job->extra->getsize_fifo) {
263 ERR("invalid backend close");
264 _return_value_to_caller(job->req_id,
265 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
269 g_hash_table_remove(backend_info_table, (gconstpointer)info.pid);
270 g_idle_add(queue_job, NULL);
275 static int __init_backend_info(void)
277 backend_info_table = g_hash_table_new_full(g_direct_hash,
278 g_direct_equal, NULL,
279 (GDestroyNotify)_free_backend_job);
281 if (pipe(pipe_sig)) {
282 ERR("create pipe failed");
286 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
287 g_io_channel_set_encoding(pipe_io, NULL, NULL);
288 g_io_channel_set_buffered(pipe_io, FALSE);
289 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
294 static void __fini_backend_info(void)
296 g_source_remove(pipe_wid);
297 g_io_channel_unref(pipe_io);
301 /*Free backend info */
302 g_hash_table_destroy(backend_info_table);
305 static void sighandler(int signo)
307 struct signal_info_t info;
308 char buf[1024] = {0, };
310 info.pid = waitpid(-1, &info.status, WNOHANG);
311 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
312 ERR("failed to write result: %s",
313 strerror_r(errno, buf, sizeof(buf)));
316 static int __register_signal_handler(void)
318 static int sig_reg = 0;
319 struct sigaction act;
324 act.sa_handler = sighandler;
325 sigemptyset(&act.sa_mask);
326 act.sa_flags = SA_NOCLDSTOP;
327 if (sigaction(SIGCHLD, &act, NULL) < 0) {
328 ERR("signal: SIGCHLD failed");
332 g_timeout_add_seconds(2, exit_server, NULL);
338 static int __check_backend_status_for_exit(void)
341 for (i = 0; i < num_of_backends; i++) {
342 if (__is_backend_busy(i))
348 static int __check_queue_status_for_exit(void)
351 for (i = 0; i < num_of_backends; i++) {
352 if (_is_queue_empty(i) == 0)
358 gboolean exit_server(void *data)
360 DBG("exit_server Start");
361 if (__check_backend_status_for_exit() &&
362 __check_queue_status_for_exit()) {
363 g_main_loop_quit(mainloop);
369 static int __check_csr(const char *path)
371 csr_cs_context_h context = NULL;
372 csr_cs_malware_h detected = NULL;
375 ret = csr_cs_context_create(&context);
376 if (ret != CSR_ERROR_NONE) {
377 ERR("Failed to create csr context");
382 ret = csr_cs_scan_file(context, path, &detected);
383 DBG("CSR result[%d]", ret);
385 csr_cs_context_destroy(context);
386 if (detected != NULL) {
387 ERR("CSR Denied[%s] Installation", path);
395 static int __kill_app(char *appid, uid_t uid)
401 is_running = aul_app_is_running_for_uid(appid, uid);
402 /* app is not running */
406 pid = aul_app_get_pid_for_uid(appid, uid);
410 ret = aul_terminate_pid_for_uid(pid, uid);
411 if (ret != AUL_R_OK) {
412 ERR("failed to terminate app(%d)", appid);
419 static int __check_app(char *appid, uid_t uid)
424 is_running = aul_app_is_running_for_uid(appid, uid);
428 pid = aul_app_get_pid_for_uid(appid, uid);
433 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
439 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
441 if (handle == NULL) {
442 perror("appinfo handle is NULL\n");
445 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
447 perror("Failed to get app exec path\n");
450 ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
452 perror("Failed to get appid\n");
455 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
457 perror("Failed to get pkgid\n");
461 if (strcmp(pdata->cmd, "kill") == 0) {
462 pdata->pid = __check_app(appid, pdata->uid);
464 ret = __kill_app(appid, pdata->uid);
465 } else if (strcmp(pdata->cmd, "check") == 0) {
466 pdata->pid = __check_app(appid, pdata->uid);
472 void free_user_context(user_ctx *ctx)
479 /* env variable ends by NULL element */
489 int set_environement(user_ctx *ctx)
500 if (ctx->uid != APPFW_UID) {
501 if (setuid(ctx->uid)) {
502 ERR("setuid failed: %d", errno);
506 if (setgid(ctx->gid)) {
507 ERR("setgid failed: %d", errno);
512 n = getgroups(0, NULL);
514 ERR("Failed to get the number of supplementary group IDs");
518 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
519 if (groups == NULL) {
520 ERR("out of memory");
524 n = getgroups(n, groups);
526 ERR("Failed to get list of supplementary group IDs");
531 groups[n++] = EXT_STORAGE_GROUP;
532 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
533 groups[n++] = MEDIA_STORAGE_GROUP;
535 if (setgroups(n, groups) < 0) {
536 ERR("setgroups failed: %d", errno);
543 /* env variable ends by NULL element */
545 if (putenv(env[i]) != 0)
552 user_ctx *get_user_context(uid_t uid)
554 /* we can use getpwnam because this is used only after a
555 * fork and just before an execv
556 * No concurrencial call can corrupt the data
557 * returned by getpwuid
559 user_ctx *context_res;
561 char buf[1024] = {0, };
562 struct passwd pwd, *result;
567 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
568 if (ret != 0 || result == NULL)
572 context_res = (user_ctx *)malloc(sizeof(user_ctx));
577 env = (char **)malloc(3 * sizeof(char *));
582 /* Build environment context */
583 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
584 env[0] = (char *)malloc((len + 1) * sizeof(char));
585 if (env[0] == NULL) {
589 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
590 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
591 env[1] = (char *)malloc((len + 1) * sizeof(char));
592 if (env[1] == NULL) {
596 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
604 /* env variable ends by NULL element */
605 while (env && env[i]) {
612 context_res->env = env;
613 context_res->uid = uid;
614 context_res->gid = pwd.pw_gid;
619 static char **__generate_argv(const char *args)
621 /* Create args vector
622 * req_id + pkgid + args
624 * vector size = # of args +
625 *(req_id + pkgid + NULL termination = 3)
626 * Last value must be NULL for execv.
634 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
635 if (FALSE == ret_parse) {
636 DBG("Failed to split args: %s", args);
637 DBG("messsage: %s", gerr->message);
642 for (i = 0; i < argcp; i++)
643 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
648 void __set_environment(gpointer user_data)
650 user_ctx *ctx = (user_ctx *)user_data;
652 if (set_environement(ctx))
653 DBG("Failed to set env for the user : %d", ctx->uid);
656 static int __fork_and_exec_with_args(char **argv, uid_t uid)
658 user_ctx *user_context;
659 GError *error = NULL;
663 user_context = get_user_context(uid);
665 DBG("Failed to getenv");
669 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
670 __set_environment, (gpointer)user_context, &pid,
673 ERR("Failed to excute backend: %s", error->message);
675 free_user_context(user_context);
679 free_user_context(user_context);
684 static int __change_job_info(struct backend_job *job, uid_t uid,
689 pkgmgrinfo_appinfo_h handle = NULL;
690 if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
691 job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
692 job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
693 job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
694 job->req_type != REQUEST_TYPE_ENABLE_APP &&
695 job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
696 return PMINFO_R_ERROR;
698 ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
699 if (ret != PMINFO_R_OK)
700 return PMINFO_R_ERROR;
702 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
703 if (ret != PMINFO_R_OK)
706 if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
708 REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
710 ret = PMINFO_R_ERROR;
714 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
715 if (ret != PMINFO_R_OK)
719 job->appid = strdup(job->pkgid);
721 job->pkgid = strdup(pkgid);
724 pkgmgrinfo_appinfo_destroy_appinfo(handle);
729 static int __process_install(struct backend_job *job)
733 char args[MAX_PKG_ARGS_LEN];
738 backend_cmd = job->backend_path;
739 if (backend_cmd == NULL)
742 req_id = g_shell_quote(job->req_id);
743 pkgid = g_shell_quote(job->pkgid);
744 if (!req_id || !pkgid)
747 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
748 req_id, pkgid, (int)job->target_uid, job->args);
750 argv = __generate_argv(args);
752 pid = __fork_and_exec_with_args(argv, APPFW_UID);
760 static int __process_mount_install(struct backend_job *job)
764 char args[MAX_PKG_ARGS_LEN];
769 backend_cmd = job->backend_path;
770 if (backend_cmd == NULL)
773 req_id = g_shell_quote(job->req_id);
774 pkgid = g_shell_quote(job->pkgid);
775 if (!req_id || !pkgid)
778 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
779 req_id, pkgid, (int)job->target_uid, job->args);
781 argv = __generate_argv(args);
783 pid = __fork_and_exec_with_args(argv, APPFW_UID);
791 static int __process_reinstall(struct backend_job *job)
795 char args[MAX_PKG_ARGS_LEN];
800 backend_cmd = job->backend_path;
801 if (backend_cmd == NULL)
804 req_id = g_shell_quote(job->req_id);
805 pkgid = g_shell_quote(job->pkgid);
806 if (!req_id || !pkgid)
809 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
810 req_id, pkgid, (int)job->target_uid);
811 argv = __generate_argv(args);
813 pid = __fork_and_exec_with_args(argv, APPFW_UID);
822 static int __process_uninstall(struct backend_job *job)
826 char args[MAX_PKG_ARGS_LEN];
829 backend_cmd = job->backend_path;
830 if (backend_cmd == NULL)
833 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
834 job->req_id, job->pkgid, (int)job->target_uid);
835 argv = __generate_argv(args);
837 pid = __fork_and_exec_with_args(argv, APPFW_UID);
844 static int __process_move(struct backend_job *job)
848 char args[MAX_PKG_ARGS_LEN];
851 backend_cmd = job->backend_path;
852 if (backend_cmd == NULL)
855 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
856 job->req_id, job->pkgid, (int)job->target_uid, job->args);
857 argv = __generate_argv(args);
859 pid = __fork_and_exec_with_args(argv, APPFW_UID);
866 static int __process_enable_pkg(struct backend_job *job)
870 char args[MAX_PKG_ARGS_LEN];
871 pkgmgrinfo_pkginfo_h pkginfo_h;
877 backend_cmd = job->backend_path;
878 if (backend_cmd == NULL)
881 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
882 job->pkgid, job->target_uid, &pkginfo_h);
883 if (ret != PMINFO_R_OK) {
884 ERR("Failed to get appinfo");
888 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
889 if (ret != PMINFO_R_OK) {
890 ERR("Failed to get global value");
891 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
895 if ((is_global && job->target_uid != GLOBAL_USER) ||
896 (!is_global && job->target_uid == GLOBAL_USER)) {
897 ERR("Invalid attempt to enable pkg");
898 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
902 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
903 if (ret != PMINFO_R_OK) {
904 ERR("Failed to get readonly value");
905 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
909 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
910 backend_cmd, job->req_id, (int)job->target_uid,
911 job->pkgid, (is_readonly) ? "--preload" : "");
912 argv = __generate_argv(args);
913 pid = __fork_and_exec_with_args(argv, APPFW_UID);
916 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
921 static int __process_disable_pkg(struct backend_job *job)
925 char args[MAX_PKG_ARGS_LEN];
926 pkgmgrinfo_pkginfo_h pkginfo_h;
932 backend_cmd = job->backend_path;
933 if (backend_cmd == NULL)
936 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
937 job->pkgid, job->target_uid, &pkginfo_h);
938 if (ret != PMINFO_R_OK) {
939 ERR("Failed to get appinfo");
943 ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
944 if (ret != PMINFO_R_OK) {
945 ERR("Failed to get global value");
946 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
950 if ((is_global && job->target_uid != GLOBAL_USER) ||
951 (!is_global && job->target_uid == GLOBAL_USER)) {
952 ERR("Invalid attempt to disable pkg");
953 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
957 ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
958 if (ret != PMINFO_R_OK) {
959 ERR("Failed to get readonly value");
960 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
964 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
965 backend_cmd, job->req_id, (int)job->target_uid,
966 job->pkgid, (is_readonly) ? "--preload" : "");
967 argv = __generate_argv(args);
969 pid = __fork_and_exec_with_args(argv, APPFW_UID);
973 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
977 static int __process_enable_app(struct backend_job *job)
980 bool is_global = false;
982 /* get actual pkgid and replace it to appid which is currently stored
985 ret = __change_job_info(job, job->target_uid, &is_global);
986 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
987 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
988 PKGMGR_INSTALLER_START_KEY_STR,
989 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
991 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
992 PKGMGR_INSTALLER_END_KEY_STR,
993 PKGMGR_INSTALLER_FAIL_EVENT_STR,
998 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
999 PKGMGR_INSTALLER_START_KEY_STR,
1000 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1002 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1003 job->target_uid, 0);
1004 if (ret != PMINFO_R_OK)
1005 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1006 PKGMGR_INSTALLER_END_KEY_STR,
1007 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1010 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1011 PKGMGR_INSTALLER_END_KEY_STR,
1012 PKGMGR_INSTALLER_OK_EVENT_STR,
1018 static int __process_disable_app(struct backend_job *job)
1021 bool is_global = false;
1023 /* get actual pkgid and replace it to appid which is currently stored
1026 ret = __change_job_info(job, job->target_uid, &is_global);
1027 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1028 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1029 PKGMGR_INSTALLER_START_KEY_STR,
1030 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1032 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1033 PKGMGR_INSTALLER_END_KEY_STR,
1034 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1039 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1040 PKGMGR_INSTALLER_START_KEY_STR,
1041 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1043 ret = __kill_app(job->appid, job->target_uid);
1045 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1046 PKGMGR_INSTALLER_END_KEY_STR,
1047 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1051 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1052 job->target_uid, 1);
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_enable_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, job->target_uid, &is_global);
1076 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1077 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1078 PKGMGR_INSTALLER_START_KEY_STR,
1079 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1081 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1082 PKGMGR_INSTALLER_END_KEY_STR,
1083 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1088 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1089 PKGMGR_INSTALLER_START_KEY_STR,
1090 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1093 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1094 job->appid, job->target_uid, 0);
1095 if (ret != PMINFO_R_OK)
1096 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1097 PKGMGR_INSTALLER_END_KEY_STR,
1098 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1101 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1102 PKGMGR_INSTALLER_END_KEY_STR,
1103 PKGMGR_INSTALLER_OK_EVENT_STR,
1109 static int __process_disable_global_app_for_uid(struct backend_job *job)
1112 bool is_global = true;
1114 /* get actual pkgid and replace it to appid which is currently stored
1117 ret = __change_job_info(job, GLOBAL_USER, &is_global);
1118 if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1119 _send_app_signal(job->target_uid, job->req_id,
1120 job->pkgid, job->pkgid,
1121 PKGMGR_INSTALLER_START_KEY_STR,
1122 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1124 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1125 PKGMGR_INSTALLER_END_KEY_STR,
1126 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1131 _send_app_signal(job->target_uid, job->req_id,
1132 job->pkgid, job->appid,
1133 PKGMGR_INSTALLER_START_KEY_STR,
1134 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1137 ret = __kill_app(job->appid, job->target_uid);
1138 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1139 job->appid, job->target_uid, 1);
1141 if (ret != PMINFO_R_OK)
1142 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1143 PKGMGR_INSTALLER_END_KEY_STR,
1144 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1147 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1148 PKGMGR_INSTALLER_END_KEY_STR,
1149 PKGMGR_INSTALLER_OK_EVENT_STR,
1155 static int __process_getsize(struct backend_job *job)
1157 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1159 char args[MAX_PKG_ARGS_LEN];
1162 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1163 backend_cmd, job->pkgid, job->args, job->caller_uid,
1164 job->req_id, job->target_uid);
1165 argv = __generate_argv(args);
1166 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1173 static int __process_getsize_sync(struct backend_job *job)
1175 static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1177 char args[MAX_PKG_ARGS_LEN];
1178 char fifo_path[PATH_MAX];
1181 snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1184 job->extra = calloc(1, sizeof(struct job_extra_info));
1186 ERR("memory alloc failed");
1190 job->extra->getsize_fifo = strdup(fifo_path);
1191 if (!job->extra->getsize_fifo) {
1192 ERR("out of memory");
1196 if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1197 ERR("failed to mkfifo");
1201 snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1202 backend_cmd, job->pkgid, job->args, job->caller_uid,
1203 job->req_id, job->target_uid);
1204 argv = __generate_argv(args);
1205 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1210 ERR("failed to execute backend");
1213 if (__setup_size_info_io(job) < 0) {
1214 ERR("failed to setup io handler");
1221 _return_value_to_caller(job->req_id,
1222 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1226 static int __process_cleardata(struct backend_job *job)
1228 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1230 char args[MAX_PKG_ARGS_LEN];
1233 if ((int)job->target_uid < REGULAR_USER)
1236 snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1237 backend_cmd, job->pkgid, job->target_uid);
1238 argv = __generate_argv(args);
1239 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1245 static int __process_clearcache(struct backend_job *job)
1247 static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1249 char args[MAX_PKG_ARGS_LEN];
1252 if ((int)job->target_uid < REGULAR_USER)
1255 snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1256 backend_cmd, job->pkgid, job->target_uid);
1257 argv = __generate_argv(args);
1258 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1264 static int __process_kill(struct backend_job *job)
1267 pkgmgrinfo_pkginfo_h handle;
1270 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1273 ERR("Failed to get handle");
1274 _return_value_to_caller(job->req_id,
1275 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1279 pdata = calloc(1, sizeof(pkgcmd_data));
1280 if (pdata == NULL) {
1281 ERR("memory alloc failed");
1282 _return_value_to_caller(job->req_id,
1283 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1286 pdata->cmd = strdup("kill");
1287 if (pdata->cmd == NULL) {
1288 ERR("out of memory");
1289 _return_value_to_caller(job->req_id,
1290 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1294 pdata->uid = job->target_uid;
1295 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1296 __pkgcmd_app_cb, pdata, job->target_uid);
1298 _return_value_to_caller(job->req_id,
1299 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1303 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1305 ERR("pkgmgrinfo_appinfo_get_list() failed");
1312 static int __process_check(struct backend_job *job)
1315 pkgmgrinfo_pkginfo_h handle;
1318 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1321 ERR("Failed to get handle");
1322 _return_value_to_caller(job->req_id,
1323 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1327 pdata = calloc(1, sizeof(pkgcmd_data));
1328 if (pdata == NULL) {
1329 ERR("memory alloc failed");
1330 _return_value_to_caller(job->req_id,
1331 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1334 pdata->cmd = strdup("check");
1335 if (pdata->cmd == NULL) {
1336 ERR("out of memory");
1337 _return_value_to_caller(job->req_id,
1338 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1342 pdata->uid = job->target_uid;
1343 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1344 __pkgcmd_app_cb, pdata, job->target_uid);
1346 _return_value_to_caller(job->req_id,
1347 g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1351 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1353 ERR("pkgmgrinfo_appinfo_get_list() failed");
1360 static int __process_generate_license_request(struct backend_job *job)
1364 char req_data[MAX_PKG_ARGS_LEN];
1365 unsigned int req_data_len;
1366 char license_url[MAX_PKG_ARGS_LEN];
1367 unsigned int license_url_len;
1369 resp_data = job->args;
1370 req_data_len = sizeof(req_data);
1371 license_url_len = sizeof(license_url);
1373 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1374 req_data, &req_data_len, license_url, &license_url_len);
1375 if (ret != TADC_SUCCESS) {
1376 ERR("drm_tizen_generate_license_request failed: %d", ret);
1377 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1378 PKGMGR_R_ESYSTEM, "", ""));
1382 _return_value_to_caller(job->req_id,
1383 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1389 static int __process_register_license(struct backend_job *job)
1394 resp_data = job->args;
1396 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1397 if (ret != TADC_SUCCESS) {
1398 ERR("drm_tizen_register_license failed: %d", ret);
1399 _return_value_to_caller(job->req_id,
1400 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1404 _return_value_to_caller(job->req_id,
1405 g_variant_new("(i)", PKGMGR_R_OK));
1410 static int __process_decrypt_package(struct backend_job *job)
1413 char *drm_file_path;
1414 char *decrypted_file_path;
1416 drm_file_path = job->pkgid;
1417 decrypted_file_path = job->args;
1419 /* TODO: check ownership of decrypted file */
1420 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1421 decrypted_file_path, strlen(decrypted_file_path));
1422 if (ret != TADC_SUCCESS) {
1423 ERR("drm_tizen_register_license failed: %d", ret);
1424 _return_value_to_caller(job->req_id,
1425 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1429 _return_value_to_caller(job->req_id,
1430 g_variant_new("(i)", PKGMGR_R_OK));
1435 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1438 bool is_global = false;
1441 ret = __change_job_info(job, job->target_uid, &is_global);
1442 if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1445 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1446 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1447 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1448 PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1451 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1453 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1454 job->appid, job->target_uid, flag);
1455 if (ret != PMINFO_R_OK)
1456 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1457 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1458 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1461 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1462 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1463 PKGMGR_INSTALLER_OK_EVENT_STR,
1469 static int __process_set_restriction_mode(struct backend_job *job)
1474 mode = atoi(job->args);
1475 ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1477 _return_value_to_caller(job->req_id,
1478 g_variant_new("(i)", ret));
1483 static int __process_unset_restriction_mode(struct backend_job *job)
1488 mode = atoi(job->args);
1489 ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1491 _return_value_to_caller(job->req_id,
1492 g_variant_new("(i)", ret));
1497 static int __process_get_restriction_mode(struct backend_job *job)
1502 ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1504 _return_value_to_caller(job->req_id,
1505 g_variant_new("(ii)", mode, ret));
1510 static int __process_set_app_label(struct backend_job *job)
1514 ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1515 job->target_uid, job->args);
1516 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1521 static int __process_migrate_external_image(struct backend_job *job)
1525 char args[MAX_PKG_ARGS_LEN];
1528 backend_cmd = job->backend_path;
1529 if (backend_cmd == NULL)
1532 snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1533 backend_cmd, job->req_id, job->pkgid,
1534 (int)job->target_uid, job->args);
1536 argv = __generate_argv(args);
1538 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1544 static int __post_process(int ret, int x, struct backend_job *job)
1547 __set_backend_free(x);
1548 _free_backend_job(job);
1550 g_hash_table_insert(backend_info_table, (gpointer)ret,
1556 gboolean queue_job(void *data)
1558 struct backend_job *job = NULL;
1562 /* Pop a job from queue */
1563 for (x = 0; x < num_of_backends; x++) {
1564 if (__is_backend_busy(x))
1567 job = _pop_queue(x);
1572 /* all backend messages queue are empty or busy */
1573 if (x == num_of_backends || job == NULL) {
1574 DBG("no job available");
1578 /* set current backend job */
1579 DBG("handle request type [%d]", job->req_type);
1581 if (TIZEN_FEATURE_CSR) {
1582 if (job->req_type == REQUEST_TYPE_INSTALL ||
1583 job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1584 job->req_type == REQUEST_TYPE_REINSTALL) {
1585 ret = __check_csr(job->pkgid);
1588 _send_fail_signal(job);
1589 _free_backend_job(job);
1595 switch (job->req_type) {
1596 case REQUEST_TYPE_INSTALL:
1597 __set_backend_busy(x);
1598 ret = __process_install(job);
1599 __post_process(ret, x, job);
1601 case REQUEST_TYPE_MOUNT_INSTALL:
1602 __set_backend_busy(x);
1603 ret = __process_mount_install(job);
1604 __post_process(ret, x, job);
1606 case REQUEST_TYPE_REINSTALL:
1607 __set_backend_busy(x);
1608 ret = __process_reinstall(job);
1609 __post_process(ret, x, job);
1611 case REQUEST_TYPE_UNINSTALL:
1612 __set_backend_busy(x);
1613 ret = __process_uninstall(job);
1614 __post_process(ret, x, job);
1616 case REQUEST_TYPE_MOVE:
1617 __set_backend_busy(x);
1618 ret = __process_move(job);
1619 __post_process(ret, x, job);
1621 case REQUEST_TYPE_ENABLE_PKG:
1622 __set_backend_busy(x);
1623 ret = __process_enable_pkg(job);
1625 _send_fail_signal(job);
1626 __post_process(ret, x, job);
1628 case REQUEST_TYPE_DISABLE_PKG:
1629 __set_backend_busy(x);
1630 ret = __process_disable_pkg(job);
1632 _send_fail_signal(job);
1633 __post_process(ret, x, job);
1635 case REQUEST_TYPE_ENABLE_APP:
1636 ret = __process_enable_app(job);
1637 _free_backend_job(job);
1639 case REQUEST_TYPE_DISABLE_APP:
1640 ret = __process_disable_app(job);
1641 _free_backend_job(job);
1643 case REQUEST_TYPE_GETSIZE:
1644 __set_backend_busy(x);
1645 ret = __process_getsize(job);
1646 __post_process(ret, x, job);
1648 case REQUEST_TYPE_GETSIZE_SYNC:
1649 __set_backend_busy(x);
1650 ret = __process_getsize_sync(job);
1652 __free_extra_info(job);
1653 __post_process(ret, x, job);
1655 case REQUEST_TYPE_CLEARDATA:
1656 __set_backend_busy(x);
1657 ret = __process_cleardata(job);
1658 __post_process(ret, x, job);
1660 case REQUEST_TYPE_CLEARCACHE:
1661 __set_backend_busy(x);
1662 ret = __process_clearcache(job);
1663 __post_process(ret, x, job);
1665 case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1666 ret = __process_enable_global_app_for_uid(job);
1667 _free_backend_job(job);
1669 case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1670 ret = __process_disable_global_app_for_uid(job);
1671 _free_backend_job(job);
1673 case REQUEST_TYPE_KILL:
1674 ret = __process_kill(job);
1675 _free_backend_job(job);
1677 case REQUEST_TYPE_CHECK:
1678 ret = __process_check(job);
1679 _free_backend_job(job);
1681 case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1682 ret = __process_generate_license_request(job);
1683 _free_backend_job(job);
1685 case REQUEST_TYPE_REGISTER_LICENSE:
1686 ret = __process_register_license(job);
1687 _free_backend_job(job);
1689 case REQUEST_TYPE_DECRYPT_PACKAGE:
1690 ret = __process_decrypt_package(job);
1691 _free_backend_job(job);
1693 case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1694 ret = __process_update_app_splash_screen(job, 1);
1695 _free_backend_job(job);
1697 case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1698 ret = __process_update_app_splash_screen(job, 0);
1699 _free_backend_job(job);
1701 case REQUEST_TYPE_SET_RESTRICTION_MODE:
1702 ret = __process_set_restriction_mode(job);
1703 _free_backend_job(job);
1705 case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1706 ret = __process_unset_restriction_mode(job);
1707 _free_backend_job(job);
1709 case REQUEST_TYPE_GET_RESTRICTION_MODE:
1710 ret = __process_get_restriction_mode(job);
1711 _free_backend_job(job);
1713 case REQUEST_TYPE_SET_APP_LABEL:
1714 ret = __process_set_app_label(job);
1715 _free_backend_job(job);
1717 case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1718 __set_backend_busy(x);
1719 ret = __process_migrate_external_image(job);
1720 __post_process(ret, x, job);
1730 int main(int argc, char *argv[])
1734 DBG("server start");
1736 r = _init_backend_queue();
1738 DBG("Queue Initialization Failed");
1742 r = __init_backend_info();
1744 DBG("backend info init failed");
1748 r = _init_request_handler();
1750 ERR("dbus init failed");
1754 if (__register_signal_handler()) {
1755 ERR("failed to register signal handler");
1759 #if !GLIB_CHECK_VERSION(2, 35, 0)
1762 mainloop = g_main_loop_new(NULL, FALSE);
1764 ERR("g_main_loop_new failed");
1768 DBG("Main loop is created.");
1770 g_main_loop_run(mainloop);
1772 DBG("Quit main loop.");
1773 _fini_request_handler();
1774 __fini_backend_info();
1775 _fini_backend_queue();
1777 DBG("package manager server terminated.");