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>
33 #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 NO_MATCHING_FILE 11
58 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
62 #define EXT_STORAGE_GROUP 10001
63 #define EXT_STORAGE_APPDATA_GROUP 10002
64 #define MEDIA_STORAGE_GROUP 10502
65 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
79 8 bit value to represent maximum 8 backends.
80 Each bit position corresponds to a queue slot which
81 is dynamically determined.
83 char backend_busy = 0;
84 extern int num_of_backends;
86 struct signal_info_t {
91 static int pipe_sig[2];
92 static GIOChannel *pipe_io;
93 static guint pipe_wid;
96 extern queue_info_map *start;
99 GMainLoop *mainloop = NULL;
104 OPERATION_INSTALL = 0,
111 static int __check_backend_status_for_exit(void);
112 static int __check_queue_status_for_exit(void);
113 static int __is_backend_busy(int position);
114 static void __set_backend_busy(int position);
115 static void __set_backend_free(int position);
116 static void sighandler(int signo);
118 gboolean exit_server(void *data);
120 /* To check whether a particular backend is free/busy*/
121 static int __is_backend_busy(int position)
123 return backend_busy & 1<<position;
125 /*To set a particular backend as busy*/
126 static void __set_backend_busy(int position)
128 backend_busy = backend_busy | 1<<position;
130 /*To set a particular backend as free */
131 static void __set_backend_free(int position)
133 backend_busy = backend_busy & ~(1<<position);
136 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
142 struct signal_info_t info;
143 backend_info *ptr = begin;
145 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
146 if (s != G_IO_STATUS_NORMAL) {
147 ERR("Signal pipe read failed: %s", err->message);
152 for (x = 0; x < num_of_backends; x++, ptr++) {
153 if (ptr && ptr->pid == info.pid)
157 if (x == num_of_backends) {
158 ERR("Unknown child exit");
162 __set_backend_free(x);
163 if (WIFSIGNALED(info.status)) {
164 __send_fail_signal(ptr);
165 DBG("backend[%s] exit with signal[%d]", ptr->pkgtype,
166 WTERMSIG(info.status));
167 } else if (WEXITSTATUS(info.status)) {
168 DBG("backend[%s] exit with error", ptr->pkgtype);
170 DBG("backend[%s] exit", ptr->pkgtype);
173 g_idle_add(queue_job, NULL);
178 static int __init_backend_info(void)
182 /*Allocate memory for holding pid, pkgtype and pkgid*/
183 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
185 DBG("Malloc Failed\n");
190 if (pipe(pipe_sig)) {
191 ERR("create pipe failed");
195 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
196 g_io_channel_set_encoding(pipe_io, NULL, NULL);
197 g_io_channel_set_buffered(pipe_io, FALSE);
198 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
203 static void __fini_backend_info(void)
205 g_source_remove(pipe_wid);
206 g_io_channel_unref(pipe_io);
210 /*Free backend info */
214 static void sighandler(int signo)
216 struct signal_info_t info;
217 char buf[1024] = {0, };
219 info.pid = waitpid(-1, &info.status, WNOHANG);
220 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
221 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
224 static int __register_signal_handler(void)
226 static int sig_reg = 0;
227 struct sigaction act;
232 act.sa_handler = sighandler;
233 sigemptyset(&act.sa_mask);
234 act.sa_flags = SA_NOCLDSTOP;
235 if (sigaction(SIGCHLD, &act, NULL) < 0) {
236 ERR("signal: SIGCHLD failed\n");
240 g_timeout_add_seconds(2, exit_server, NULL);
246 static int __check_backend_status_for_exit(void)
249 for (i = 0; i < num_of_backends; i++) {
250 if (__is_backend_busy(i))
256 static int __check_queue_status_for_exit(void)
258 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
259 queue_info_map *ptr = NULL;
264 for (i = 0; i < entries; i++) {
265 if (ptr->queue_slot <= slot) {
269 slot = ptr->queue_slot;
274 for (i = 0; i < num_of_backends; i++) {
281 gboolean exit_server(void *data)
283 DBG("exit_server Start\n");
284 if (__check_backend_status_for_exit() &&
285 __check_queue_status_for_exit()) {
286 if (!getenv("PMS_STANDALONE")) {
287 g_main_loop_quit(mainloop);
294 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
298 if (buf == NULL || path == NULL)
300 fd = open(path, O_RDONLY);
303 ret = read(fd, buf, size - 1);
313 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
314 const char *cmdline, const char *apppath)
319 if (strcmp(cmdline, apppath) == 0) {
323 ERR("getpgid failed, errno(%d)", errno);
332 #ifdef TIZEN_FEATURE_CSR
333 static int __check_csr(backend_info *ptr)
335 csr_cs_context_h context = NULL;
336 csr_cs_malware_h detected = NULL;
339 ret = csr_cs_context_create(&context);
340 if (ret != CSR_ERROR_NONE) {
341 ERR("Failed to create csr context");
346 ret = csr_cs_scan_file(context, ptr->pkgid, &detected);
347 DBG("CSR result[%d]", ret);
349 csr_cs_context_destroy(context);
350 if (detected != NULL) {
351 ERR("CSR Denied[%s] Installation", ptr->pkgid);
360 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
363 struct dirent dentry, *result;
366 char buf[1024] = {'\0'};
369 dp = opendir("/proc");
373 for (ret = readdir_r(dp, &dentry, &result);
374 ret == 0 && result != NULL;
375 ret = readdir_r(dp, &dentry, &result)) {
376 if (!isdigit(dentry.d_name[0]))
379 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
380 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
384 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
393 ERR("getpgid failed, errno(%d)", errno);
396 if (killpg(pgid, SIGKILL) < 0) {
398 ERR("killpg failed, errno(%d)", errno);
409 static void __make_pid_info_file(char *req_key, int pid, uid_t uid)
414 char buf[MAX_PKG_TYPE_LEN] = {0};
415 char info_file[PATH_MAX] = {'\0'};
417 struct passwd *pwd_result;
422 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
423 if (ret != 0 || pwd_result == NULL) {
424 ERR("get uid failed(%d) for user(%d)", ret, uid);
427 DBG("uid(%d), gid(%d)", uid, pwd.pw_gid);
429 snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
431 DBG("info_path(%s)", info_file);
432 file = fopen(info_file, "w");
434 ERR("Couldn't open the file(%s)", info_file);
438 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
439 fwrite(buf, 1, strlen(buf), file);
443 if (fchmod(fd, 0777) < 0)
444 ERR("chmod failed, errno(%d)", errno);
445 if (fchown(fd, uid, pwd.pw_gid) < 0)
446 ERR("chown failed, errno(%d)", errno);
451 static int __kill_app(char *appid, uid_t uid)
453 pkgmgrinfo_appinfo_h appinfo;
454 int ret = PMINFO_R_ERROR;
457 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
458 if (ret != PMINFO_R_OK)
459 return PMINFO_R_ERROR;
461 ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
462 if (ret != PMINFO_R_OK) {
463 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
464 return PMINFO_R_ERROR;
467 ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
468 if (ret != PMINFO_R_OK)
469 DBG("failed to kill app[%s], exec[%s]", appid, exec);
471 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
475 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
481 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
483 if (handle == NULL) {
484 perror("appinfo handle is NULL\n");
487 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
489 perror("Failed to get app exec path\n");
492 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
494 perror("Failed to get pkgid\n");
498 if (strcmp(pdata->cmd, "kill") == 0)
499 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
500 else if (strcmp(pdata->cmd, "check") == 0)
501 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
503 __make_pid_info_file(pkgid, pid, pdata->uid);
508 void free_user_context(user_ctx* ctx)
515 /* env variable ends by NULL element */
525 int set_environement(user_ctx *ctx)
536 n = getgroups(0, NULL);
538 ERR("Failed to get the number of supplementary group IDs");
542 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
543 if (groups == NULL) {
544 ERR("out of memory");
548 n = getgroups(n, groups);
550 ERR("Failed to get list of supplementary group IDs");
555 groups[n++] = EXT_STORAGE_GROUP;
556 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
557 groups[n++] = MEDIA_STORAGE_GROUP;
559 if (setgroups(n, groups) < 0) {
560 ERR("setgroups failed: %d", errno);
567 /* env variable ends by NULL element */
569 if (putenv(env[i]) != 0)
576 user_ctx *get_user_context(uid_t uid)
578 /* we can use getpwnam because this is used only after a
579 * fork and just before an execv
580 * No concurrencial call can corrupt the data
581 * returned by getpwuid
583 user_ctx *context_res;
585 char buf[1024] = {0, };
586 struct passwd pwd, *result;
591 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
592 if (ret != 0 || result == NULL)
596 context_res = (user_ctx *)malloc(sizeof(user_ctx));
601 env = (char **)malloc(3 * sizeof(char *));
606 /* Build environment context */
607 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
608 env[0] = (char *)malloc((len + 1) * sizeof(char));
609 if (env[0] == NULL) {
613 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
614 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
615 env[1] = (char *)malloc((len + 1) * sizeof(char));
616 if (env[1] == NULL) {
620 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
628 /* env variable ends by NULL element */
629 while (env && env[i]) {
636 context_res->env = env;
637 context_res->uid = uid;
638 context_res->gid = pwd.pw_gid;
643 static char **__generate_argv(const char *args)
645 /* Create args vector
646 * req_id + pkgid + args
648 * vector size = # of args +
649 *(req_id + pkgid + NULL termination = 3)
650 * Last value must be NULL for execv.
658 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
659 if (FALSE == ret_parse) {
660 DBG("Failed to split args: %s", args);
661 DBG("messsage: %s", gerr->message);
666 for (i = 0; i < argcp; i++)
667 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
672 void __set_environment(gpointer user_data)
674 user_ctx *ctx = (user_ctx *)user_data;
676 if (set_environement(ctx))
677 DBG("Failed to set env for the user : %d", ctx->uid);
680 static int __fork_and_exec_with_args(char **argv, uid_t uid)
682 user_ctx* user_context;
683 GError *error = NULL;
687 user_context = get_user_context(uid);
689 DBG("Failed to getenv");
693 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
694 __set_environment, (gpointer)user_context, &pid,
697 ERR("Failed to excute backend: %s", error->message);
701 free_user_context(user_context);
706 static int __change_item_info(pm_dbus_msg *item, uid_t uid, bool *is_global)
710 pkgmgrinfo_appinfo_h handle = NULL;
712 switch (item->req_type) {
713 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
714 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
715 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
716 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
717 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
719 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
720 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
721 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
724 return PMINFO_R_ERROR;
727 if (ret != PMINFO_R_OK)
728 return PMINFO_R_ERROR;
730 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
731 if (ret != PMINFO_R_OK)
734 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
735 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
737 ret = PMINFO_R_ERROR;
739 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
740 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
742 ret = PMINFO_R_ERROR;
746 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
747 if (ret != PMINFO_R_OK)
750 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
751 memset((item->pkgid), 0, MAX_PKG_NAME_LEN);
752 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
755 pkgmgrinfo_appinfo_destroy_appinfo(handle);
760 static int __process_install(pm_dbus_msg *item)
764 char args[MAX_PKG_ARGS_LEN] = {'\0', };
767 backend_cmd = _get_backend_cmd(item->pkg_type);
768 if (backend_cmd == NULL)
771 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
772 item->req_id, item->pkgid, (int)item->uid, item->args);
774 argv = __generate_argv(args);
776 pid = __fork_and_exec_with_args(argv, APPFW_UID);
783 static int __process_mount_install(pm_dbus_msg *item)
787 char args[MAX_PKG_ARGS_LEN] = {'\0', };
790 backend_cmd = _get_backend_cmd(item->pkg_type);
791 if (backend_cmd == NULL)
794 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
795 item->req_id, item->pkgid, (int)item->uid, item->args);
797 argv = __generate_argv(args);
799 pid = __fork_and_exec_with_args(argv, APPFW_UID);
806 static int __process_reinstall(pm_dbus_msg *item)
810 char args[MAX_PKG_ARGS_LEN];
813 backend_cmd = _get_backend_cmd(item->pkg_type);
814 if (backend_cmd == NULL)
817 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
818 item->req_id, item->pkgid, (int)item->uid);
819 argv = __generate_argv(args);
821 pid = __fork_and_exec_with_args(argv, APPFW_UID);
829 static int __process_uninstall(pm_dbus_msg *item)
833 char args[MAX_PKG_ARGS_LEN];
836 backend_cmd = _get_backend_cmd(item->pkg_type);
837 if (backend_cmd == NULL)
840 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
841 item->req_id, item->pkgid, (int)item->uid);
842 argv = __generate_argv(args);
844 pid = __fork_and_exec_with_args(argv, APPFW_UID);
852 static int __process_move(pm_dbus_msg *item)
856 char args[MAX_PKG_ARGS_LEN];
859 backend_cmd = _get_backend_cmd(item->pkg_type);
860 if (backend_cmd == NULL)
863 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
864 item->req_id, item->pkgid, (int)item->uid, item->args);
865 argv = __generate_argv(args);
867 pid = __fork_and_exec_with_args(argv, APPFW_UID);
875 static int __process_enable_pkg(pm_dbus_msg *item)
879 char args[MAX_PKG_ARGS_LEN];
882 backend_cmd = _get_backend_cmd(item->pkg_type);
883 if (backend_cmd == NULL)
886 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s", backend_cmd,
887 item->req_id, (int)item->uid, item->pkgid);
888 argv = __generate_argv(args);
890 pid = __fork_and_exec_with_args(argv, APPFW_UID);
898 static int __process_disable_pkg(pm_dbus_msg *item)
902 char args[MAX_PKG_ARGS_LEN];
905 backend_cmd = _get_backend_cmd(item->pkg_type);
906 if (backend_cmd == NULL)
909 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s", backend_cmd,
910 item->req_id, (int)item->uid, item->pkgid);
911 argv = __generate_argv(args);
913 pid = __fork_and_exec_with_args(argv, APPFW_UID);
921 static int __process_enable_app(pm_dbus_msg *item)
924 bool is_global = false;
926 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
927 PKGMGR_INSTALLER_START_KEY_STR,
928 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, item->req_type);
930 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
931 ret = __change_item_info(item, item->uid, &is_global);
932 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
933 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
934 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
939 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
940 if (ret != PMINFO_R_OK)
941 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
942 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
945 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
946 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
953 static int __process_disable_app(pm_dbus_msg *item)
956 bool is_global = false;
958 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
959 PKGMGR_INSTALLER_START_KEY_STR,
960 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, item->req_type);
962 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
963 ret = __change_item_info(item, item->uid, &is_global);
964 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
965 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
966 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
971 ret = __kill_app(item->appid, item->uid);
972 if (ret != PMINFO_R_OK) {
973 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
974 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
978 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
979 if (ret != PMINFO_R_OK)
980 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
981 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
984 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
985 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
991 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
994 bool is_global = true;
996 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
997 PKGMGR_INSTALLER_START_KEY_STR,
998 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID, item->req_type);
1000 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1001 ret = __change_item_info(item, item->uid, &is_global);
1002 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1003 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1004 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1009 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
1010 if (ret != PMINFO_R_OK)
1011 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1012 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1015 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1016 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1022 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
1025 bool is_global = true;
1027 __send_app_signal(item->uid, item->req_id,
1028 item->pkgid, item->pkgid,
1029 PKGMGR_INSTALLER_START_KEY_STR,
1030 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID, item->req_type);
1032 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1033 ret = __change_item_info(item, GLOBAL_USER, &is_global);
1034 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1035 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1036 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1041 ret = __kill_app(item->appid, item->uid);
1042 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid,
1045 if (ret != PMINFO_R_OK)
1046 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1047 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1050 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1051 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1057 static int __process_getsize(pm_dbus_msg *item)
1059 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1061 char args[MAX_PKG_ARGS_LEN];
1064 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1065 item->args, item->req_id);
1066 argv = __generate_argv(args);
1067 pid = __fork_and_exec_with_args(argv, item->uid);
1074 static int __process_cleardata(pm_dbus_msg *item)
1078 char args[MAX_PKG_ARGS_LEN];
1081 backend_cmd = _get_backend_cmd(item->pkg_type);
1082 if (backend_cmd == NULL)
1085 /* TODO: set movetype */
1086 snprintf(args, sizeof(args), "%s -k %s -c %s -u %d", backend_cmd,
1087 item->req_id, item->pkgid, (int)item->uid);
1088 argv = __generate_argv(args);
1090 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1098 static int __process_clearcache(pm_dbus_msg *item)
1100 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1102 char args[MAX_PKG_ARGS_LEN];
1105 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1106 argv = __generate_argv(args);
1107 pid = __fork_and_exec_with_args(argv, item->uid);
1114 static int __process_kill(pm_dbus_msg *item)
1117 pkgmgrinfo_pkginfo_h handle;
1118 pkgcmd_data *pdata = NULL;
1120 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1123 ERR("Failed to get handle");
1127 pdata = calloc(1, sizeof(pkgcmd_data));
1128 if (pdata == NULL) {
1129 ERR("memory alloc failed");
1132 pdata->cmd = strdup("kill");
1133 if (pdata->cmd == NULL) {
1134 ERR("out of memory");
1139 pdata->uid = item->uid;
1140 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1141 __pkgcmd_app_cb, pdata, item->uid);
1145 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1147 ERR("pkgmgrinfo_appinfo_get_list() failed");
1154 static int __process_check(pm_dbus_msg *item)
1157 pkgmgrinfo_pkginfo_h handle;
1158 pkgcmd_data *pdata = NULL;
1160 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1163 ERR("Failed to get handle");
1167 pdata = calloc(1, sizeof(pkgcmd_data));
1168 if (pdata == NULL) {
1169 ERR("memory alloc failed");
1172 pdata->cmd = strdup("check");
1173 if (pdata->cmd == NULL) {
1174 ERR("out of memory");
1179 pdata->uid = item->uid;
1180 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1181 __pkgcmd_app_cb, pdata, item->uid);
1185 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1187 ERR("pkgmgrinfo_appinfo_get_list() failed");
1194 static int __process_generate_license_request(pm_dbus_msg *item)
1198 char req_data[MAX_PKG_ARGS_LEN];
1199 unsigned int req_data_len;
1200 char license_url[MAX_PKG_ARGS_LEN];
1201 unsigned int license_url_len;
1203 resp_data = item->args;
1204 req_data_len = sizeof(req_data);
1205 license_url_len = sizeof(license_url);
1207 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1208 req_data, &req_data_len, license_url, &license_url_len);
1209 if (ret != TADC_SUCCESS) {
1210 ERR("drm_tizen_generate_license_request failed: %d", ret);
1211 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1212 PKGMGR_R_ESYSTEM, "", ""));
1216 __return_value_to_caller(item->req_id,
1217 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1223 static int __process_register_license(pm_dbus_msg *item)
1228 resp_data = item->args;
1230 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1231 if (ret != TADC_SUCCESS) {
1232 ERR("drm_tizen_register_license failed: %d", ret);
1233 __return_value_to_caller(item->req_id,
1234 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1238 __return_value_to_caller(item->req_id,
1239 g_variant_new("(i)", PKGMGR_R_OK));
1244 static int __process_decrypt_package(pm_dbus_msg *item)
1247 char *drm_file_path;
1248 char *decrypted_file_path;
1250 drm_file_path = item->pkgid;
1251 decrypted_file_path = item->args;
1253 /* TODO: check ownership of decrypted file */
1254 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1255 decrypted_file_path, strlen(decrypted_file_path));
1256 if (ret != TADC_SUCCESS) {
1257 ERR("drm_tizen_register_license failed: %d", ret);
1258 __return_value_to_caller(item->req_id,
1259 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1263 __return_value_to_caller(item->req_id,
1264 g_variant_new("(i)", PKGMGR_R_OK));
1269 static int __process_update_app_splash_screen(pm_dbus_msg *item, int flag)
1272 bool is_global = false;
1275 ret = __change_item_info(item, item->uid, &is_global);
1276 if (ret != PMINFO_R_OK || strlen(item->appid) == 0)
1279 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1280 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1281 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1282 PKGMGR_INSTALLER_START_KEY_STR, val, item->req_type);
1285 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
1286 item->appid, item->uid, flag);
1288 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1289 item->appid, item->uid, flag);
1290 if (ret != PMINFO_R_OK)
1291 __send_app_signal(item->uid, item->req_id, item->pkgid,
1292 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1293 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1296 __send_app_signal(item->uid, item->req_id, item->pkgid,
1297 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1298 PKGMGR_INSTALLER_OK_EVENT_STR,
1304 static int __process_set_restriction_mode(pm_dbus_msg *item)
1309 mode = atoi(item->args);
1310 ret = _restriction_mode_set(item->uid, item->pkgid, mode);
1312 __return_value_to_caller(item->req_id,
1313 g_variant_new("(i)", ret));
1318 static int __process_unset_restriction_mode(pm_dbus_msg *item)
1323 mode = atoi(item->args);
1324 ret = _restriction_mode_unset(item->uid, item->pkgid, mode);
1326 __return_value_to_caller(item->req_id,
1327 g_variant_new("(i)", ret));
1332 static int __process_get_restriction_mode(pm_dbus_msg *item)
1337 ret = _restriction_mode_get(item->uid, item->pkgid, &mode);
1339 __return_value_to_caller(item->req_id,
1340 g_variant_new("(ii)", mode, ret));
1345 gboolean queue_job(void *data)
1347 pm_dbus_msg *item = NULL;
1352 /* Pop a job from queue */
1353 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1354 if (__is_backend_busy(x))
1357 item = _pm_queue_pop(x);
1358 if (item && item->req_type != -1)
1363 /* all backend messages queue are empty or busy */
1364 if (x == num_of_backends)
1367 /*save pkg type and pkg name for future*/
1368 strncpy(ptr->req_id, item->req_id, MAX_REQ_ID_LEN - 1);
1369 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN - 1);
1370 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN - 1);
1371 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN - 1);
1372 memset((item->appid), 0, MAX_PKG_NAME_LEN);
1373 ptr->uid = item->uid;
1374 ptr->req_type = item->req_type;
1375 DBG("handle request type [%d]", item->req_type);
1377 #ifdef TIZEN_FEATURE_CSR
1378 if (item->req_type == PKGMGR_REQUEST_TYPE_INSTALL ||
1379 item->req_type == PKGMGR_REQUEST_TYPE_MOUNT_INSTALL ||
1380 item->req_type == PKGMGR_REQUEST_TYPE_REINSTALL) {
1381 ret = __check_csr(ptr);
1384 __send_fail_signal(ptr);
1390 switch (item->req_type) {
1391 case PKGMGR_REQUEST_TYPE_INSTALL:
1392 __set_backend_busy(x);
1393 ret = __process_install(item);
1395 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
1396 __set_backend_busy(x);
1397 ret = __process_mount_install(item);
1399 case PKGMGR_REQUEST_TYPE_REINSTALL:
1400 __set_backend_busy(x);
1401 ret = __process_reinstall(item);
1403 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1404 __set_backend_busy(x);
1405 ret = __process_uninstall(item);
1407 case PKGMGR_REQUEST_TYPE_MOVE:
1408 __set_backend_busy(x);
1409 ret = __process_move(item);
1411 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1412 ret = __process_enable_pkg(item);
1414 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1415 ret = __process_disable_pkg(item);
1417 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1418 ret = __process_enable_app(item);
1420 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1421 ret = __process_disable_app(item);
1423 case PKGMGR_REQUEST_TYPE_GETSIZE:
1424 __set_backend_busy(x);
1425 ret = __process_getsize(item);
1427 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1428 __set_backend_busy(x);
1429 ret = __process_cleardata(item);
1431 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1432 __set_backend_busy(x);
1433 ret = __process_clearcache(item);
1435 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1436 ret = __process_enable_global_app_for_uid(item);
1438 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1439 ret = __process_disable_global_app_for_uid(item);
1441 case PKGMGR_REQUEST_TYPE_KILL:
1442 ret = __process_kill(item);
1444 case PKGMGR_REQUEST_TYPE_CHECK:
1445 ret = __process_check(item);
1447 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1448 ret = __process_generate_license_request(item);
1450 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1451 ret = __process_register_license(item);
1453 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1454 ret = __process_decrypt_package(item);
1456 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1457 ret = __process_update_app_splash_screen(item, 1);
1459 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1460 ret = __process_update_app_splash_screen(item, 0);
1462 case PKGMGR_REQUEST_TYPE_SET_RESTRICTION_MODE:
1463 ret = __process_set_restriction_mode(item);
1465 case PKGMGR_REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1466 ret = __process_unset_restriction_mode(item);
1468 case PKGMGR_REQUEST_TYPE_GET_RESTRICTION_MODE:
1469 ret = __process_get_restriction_mode(item);
1483 #define IS_WHITESPACE(CHAR) \
1484 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1486 void _app_str_trim(char *input)
1488 char *trim_str = input;
1493 while (*input != 0) {
1494 if (!IS_WHITESPACE(*input)) {
1505 char *_get_backend_cmd(char *type)
1508 char buffer[1024] = { 0 };
1509 char *command = NULL;
1512 fp = fopen(PKG_CONF_PATH, "r");
1517 while (fgets(buffer, 1024, fp) != NULL) {
1518 if (buffer[0] == '#')
1521 _app_str_trim(buffer);
1523 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1524 DBG("buffer [%s]", buffer);
1525 path = path + strlen(PKG_BACKEND);
1526 DBG("path [%s]", path);
1529 (char *)malloc(sizeof(char) * strlen(path) +
1531 if (command == NULL) {
1536 size = strlen(path) + strlen(type) + 1;
1537 snprintf(command, size, "%s%s", path, type);
1538 command[strlen(path) + strlen(type)] = '\0';
1539 DBG("command [%s]", command);
1547 memset(buffer, 0x00, 1024);
1553 return NULL; /* cannot find proper command */
1556 int main(int argc, char *argv[])
1560 DBG("server start");
1562 r = _pm_queue_init();
1564 DBG("Queue Initialization Failed\n");
1568 r = __init_backend_info();
1570 DBG("backend info init failed");
1574 r = __init_request_handler();
1576 ERR("dbus init failed");
1580 if (__register_signal_handler()) {
1581 ERR("failed to register signal handler");
1585 #if !GLIB_CHECK_VERSION(2, 35, 0)
1588 mainloop = g_main_loop_new(NULL, FALSE);
1590 ERR("g_main_loop_new failed");
1594 DBG("Main loop is created.");
1596 g_main_loop_run(mainloop);
1598 DBG("Quit main loop.");
1599 __fini_request_handler();
1600 __fini_backend_info();
1603 DBG("package manager server terminated.");