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>
46 #include "pkgmgr_installer.h"
47 #include "pkgmgr-server.h"
49 #include "package-manager.h"
52 #define NO_MATCHING_FILE 11
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]))
76 8 bit value to represent maximum 8 backends.
77 Each bit position corresponds to a queue slot which
78 is dynamically determined.
80 char backend_busy = 0;
81 extern int num_of_backends;
83 struct signal_info_t {
88 static int pipe_sig[2];
89 static GIOChannel *pipe_io;
90 static guint pipe_wid;
93 extern queue_info_map *start;
96 GMainLoop *mainloop = NULL;
101 OPERATION_INSTALL = 0,
108 static int __check_backend_status_for_exit(void);
109 static int __check_queue_status_for_exit(void);
110 static int __is_backend_busy(int position);
111 static void __set_backend_busy(int position);
112 static void __set_backend_free(int position);
113 static void sighandler(int signo);
115 gboolean exit_server(void *data);
117 /* To check whether a particular backend is free/busy*/
118 static int __is_backend_busy(int position)
120 return backend_busy & 1<<position;
122 /*To set a particular backend as busy*/
123 static void __set_backend_busy(int position)
125 backend_busy = backend_busy | 1<<position;
127 /*To set a particular backend as free */
128 static void __set_backend_free(int position)
130 backend_busy = backend_busy & ~(1<<position);
133 static void __send_app_signal(uid_t uid, const char *req_id,
134 const char *pkgid, const char *appid,
135 const char *key, const char *val, int req_type)
137 pkgmgr_installer *pi;
139 pi = pkgmgr_installer_new();
141 DBG("Failure in creating the pkgmgr_installer object");
145 if (pkgmgr_installer_set_uid(pi, uid))
149 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
150 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
151 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP))
154 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
155 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
156 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP))
159 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
160 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN))
163 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
164 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN))
168 DBG("Unsupported req_type[%d]", req_type);
172 if (pkgmgr_installer_set_session_id(pi, req_id))
174 pkgmgr_installer_send_app_signal(pi, "app", pkgid, appid, key, val);
177 pkgmgr_installer_free(pi);
182 static void __send_fail_signal(backend_info *info)
185 pkgmgr_installer *pi;
186 pi = pkgmgr_installer_new();
188 ERR("Failure in creating the pkgmgr_installer object");
191 pkgmgr_installer_set_session_id(pi, info->req_id);
192 switch (info->req_type) {
193 case PKGMGR_REQUEST_TYPE_INSTALL:
194 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
195 case PKGMGR_REQUEST_TYPE_REINSTALL:
196 req_type = PKGMGR_REQ_INSTALL;
198 case PKGMGR_REQUEST_TYPE_UNINSTALL:
199 req_type = PKGMGR_REQ_UNINSTALL;
201 case PKGMGR_REQUEST_TYPE_MOVE:
202 req_type = PKGMGR_REQ_MOVE;
204 case PKGMGR_REQUEST_TYPE_GETSIZE:
205 req_type = PKGMGR_REQ_GETSIZE;
208 req_type = PKGMGR_REQ_INVALID;
211 pkgmgr_installer_set_request_type(pi, req_type);
212 pkgmgr_installer_send_signal(pi, info->pkgtype, info->pkgid, "end", "fail");
213 pkgmgr_installer_free(pi);
217 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
223 struct signal_info_t info;
224 backend_info *ptr = begin;
226 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
227 if (s != G_IO_STATUS_NORMAL) {
228 ERR("Signal pipe read failed: %s", err->message);
233 for (x = 0; x < num_of_backends; x++, ptr++) {
234 if (ptr && ptr->pid == info.pid)
238 if (x == num_of_backends) {
239 ERR("Unknown child exit");
243 __set_backend_free(x);
244 if (WIFSIGNALED(info.status)) {
245 __send_fail_signal(ptr);
246 DBG("backend[%s] exit with signal[%d]", ptr->pkgtype,
247 WTERMSIG(info.status));
248 } else if (WEXITSTATUS(info.status)) {
249 DBG("backend[%s] exit with error", ptr->pkgtype);
251 DBG("backend[%s] exit", ptr->pkgtype);
254 g_idle_add(queue_job, NULL);
259 static int __init_backend_info(void)
263 /*Allocate memory for holding pid, pkgtype and pkgid*/
264 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
266 DBG("Malloc Failed\n");
271 if (pipe(pipe_sig)) {
272 ERR("create pipe failed");
276 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
277 g_io_channel_set_encoding(pipe_io, NULL, NULL);
278 g_io_channel_set_buffered(pipe_io, FALSE);
279 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
284 static void __fini_backend_info(void)
286 g_source_remove(pipe_wid);
287 g_io_channel_unref(pipe_io);
291 /*Free backend info */
295 static void sighandler(int signo)
297 struct signal_info_t info;
298 char buf[1024] = {0, };
300 info.pid = waitpid(-1, &info.status, WNOHANG);
301 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
302 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
305 static int __register_signal_handler(void)
307 static int sig_reg = 0;
308 struct sigaction act;
313 act.sa_handler = sighandler;
314 sigemptyset(&act.sa_mask);
315 act.sa_flags = SA_NOCLDSTOP;
316 if (sigaction(SIGCHLD, &act, NULL) < 0) {
317 ERR("signal: SIGCHLD failed\n");
321 g_timeout_add_seconds(2, exit_server, NULL);
327 static int __check_backend_status_for_exit(void)
330 for (i = 0; i < num_of_backends; i++) {
331 if (__is_backend_busy(i))
337 static int __check_queue_status_for_exit(void)
339 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
340 queue_info_map *ptr = NULL;
345 for (i = 0; i < entries; i++) {
346 if (ptr->queue_slot <= slot) {
350 slot = ptr->queue_slot;
355 for (i = 0; i < num_of_backends; i++) {
362 gboolean exit_server(void *data)
364 DBG("exit_server Start\n");
365 if (__check_backend_status_for_exit() &&
366 __check_queue_status_for_exit()) {
367 if (!getenv("PMS_STANDALONE")) {
368 g_main_loop_quit(mainloop);
375 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
379 if (buf == NULL || path == NULL)
381 fd = open(path, O_RDONLY);
384 ret = read(fd, buf, size - 1);
394 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
395 const char *cmdline, const char *apppath)
400 if (strcmp(cmdline, apppath) == 0) {
404 ERR("getpgid failed, errno(%d)", errno);
413 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
416 struct dirent dentry, *result;
419 char buf[1024] = {'\0'};
422 dp = opendir("/proc");
426 for (ret = readdir_r(dp, &dentry, &result);
427 ret == 0 && result != NULL;
428 ret = readdir_r(dp, &dentry, &result)) {
429 if (!isdigit(dentry.d_name[0]))
432 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
433 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
437 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
446 ERR("getpgid failed, errno(%d)", errno);
449 if (killpg(pgid, SIGKILL) < 0) {
451 ERR("killpg failed, errno(%d)", errno);
462 static void __make_pid_info_file(char *req_key, int pid, uid_t uid)
467 char buf[MAX_PKG_TYPE_LEN] = {0};
468 char info_file[PATH_MAX] = {'\0'};
470 struct passwd *pwd_result;
475 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
476 if (ret != 0 || pwd_result == NULL) {
477 ERR("get uid failed(%d) for user(%d)", ret, uid);
480 DBG("uid(%d), gid(%d)", uid, pwd.pw_gid);
482 snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
484 DBG("info_path(%s)", info_file);
485 file = fopen(info_file, "w");
487 ERR("Couldn't open the file(%s)", info_file);
491 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
492 fwrite(buf, 1, strlen(buf), file);
496 if (fchmod(fd, 0777) < 0)
497 ERR("chmod failed, errno(%d)", errno);
498 if (fchown(fd, uid, pwd.pw_gid) < 0)
499 ERR("chown failed, errno(%d)", errno);
504 static int __kill_app(char *appid, uid_t uid)
506 pkgmgrinfo_appinfo_h appinfo;
507 int ret = PMINFO_R_ERROR;
510 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
511 if (ret != PMINFO_R_OK)
512 return PMINFO_R_ERROR;
514 ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
515 if (ret != PMINFO_R_OK) {
516 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
517 return PMINFO_R_ERROR;
520 ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
521 if (ret != PMINFO_R_OK)
522 DBG("failed to kill app[%s], exec[%s]", appid, exec);
524 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
528 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
534 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
536 if (handle == NULL) {
537 perror("appinfo handle is NULL\n");
540 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
542 perror("Failed to get app exec path\n");
545 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
547 perror("Failed to get pkgid\n");
551 if (strcmp(pdata->cmd, "kill") == 0)
552 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
553 else if (strcmp(pdata->cmd, "check") == 0)
554 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
556 __make_pid_info_file(pkgid, pid, pdata->uid);
561 void free_user_context(user_ctx* ctx)
568 /* env variable ends by NULL element */
578 int set_environement(user_ctx *ctx)
589 n = getgroups(0, NULL);
591 ERR("Failed to get the number of supplementary group IDs");
595 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
596 if (groups == NULL) {
597 ERR("out of memory");
601 n = getgroups(n, groups);
603 ERR("Failed to get list of supplementary group IDs");
608 groups[n++] = EXT_STORAGE_GROUP;
609 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
610 groups[n++] = MEDIA_STORAGE_GROUP;
612 if (setgroups(n, groups) < 0) {
613 ERR("setgroups failed: %d", errno);
620 /* env variable ends by NULL element */
622 if (putenv(env[i]) != 0)
629 user_ctx *get_user_context(uid_t uid)
631 /* we can use getpwnam because this is used only after a
632 * fork and just before an execv
633 * No concurrencial call can corrupt the data
634 * returned by getpwuid
636 user_ctx *context_res;
638 char buf[1024] = {0, };
639 struct passwd pwd, *result;
644 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
645 if (ret != 0 || result == NULL)
649 context_res = (user_ctx *)malloc(sizeof(user_ctx));
654 env = (char **)malloc(3 * sizeof(char *));
659 /* Build environment context */
660 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
661 env[0] = (char *)malloc((len + 1) * sizeof(char));
662 if (env[0] == NULL) {
666 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
667 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
668 env[1] = (char *)malloc((len + 1) * sizeof(char));
669 if (env[1] == NULL) {
673 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
681 /* env variable ends by NULL element */
682 while (env && env[i]) {
689 context_res->env = env;
690 context_res->uid = uid;
691 context_res->gid = pwd.pw_gid;
696 static char **__generate_argv(const char *args)
698 /* Create args vector
699 * req_id + pkgid + args
701 * vector size = # of args +
702 *(req_id + pkgid + NULL termination = 3)
703 * Last value must be NULL for execv.
711 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
712 if (FALSE == ret_parse) {
713 DBG("Failed to split args: %s", args);
714 DBG("messsage: %s", gerr->message);
719 for (i = 0; i < argcp; i++)
720 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
725 void __set_environment(gpointer user_data)
727 user_ctx *ctx = (user_ctx *)user_data;
729 if (set_environement(ctx))
730 DBG("Failed to set env for the user : %d", ctx->uid);
733 static int __fork_and_exec_with_args(char **argv, uid_t uid)
735 user_ctx* user_context;
736 GError *error = NULL;
740 user_context = get_user_context(uid);
742 DBG("Failed to getenv");
746 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
747 __set_environment, (gpointer)user_context, &pid,
750 ERR("Failed to excute backend: %s", error->message);
754 free_user_context(user_context);
759 static int __change_item_info(pm_dbus_msg *item, uid_t uid, bool *is_global)
763 pkgmgrinfo_appinfo_h handle = NULL;
765 switch (item->req_type) {
766 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
767 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
768 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
769 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
770 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
772 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
773 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
774 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
777 return PMINFO_R_ERROR;
780 if (ret != PMINFO_R_OK)
781 return PMINFO_R_ERROR;
783 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
784 if (ret != PMINFO_R_OK)
787 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
788 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
790 ret = PMINFO_R_ERROR;
792 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
793 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
795 ret = PMINFO_R_ERROR;
799 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
800 if (ret != PMINFO_R_OK)
803 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
804 memset((item->pkgid), 0, MAX_PKG_NAME_LEN);
805 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
808 pkgmgrinfo_appinfo_destroy_appinfo(handle);
813 static int __process_install(pm_dbus_msg *item)
817 char args[MAX_PKG_ARGS_LEN] = {'\0', };
820 backend_cmd = _get_backend_cmd(item->pkg_type);
821 if (backend_cmd == NULL)
824 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
825 item->req_id, item->pkgid, (int)item->uid, item->args);
827 argv = __generate_argv(args);
829 pid = __fork_and_exec_with_args(argv, APPFW_UID);
836 static int __process_mount_install(pm_dbus_msg *item)
840 char args[MAX_PKG_ARGS_LEN] = {'\0', };
843 backend_cmd = _get_backend_cmd(item->pkg_type);
844 if (backend_cmd == NULL)
847 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
848 item->req_id, item->pkgid, (int)item->uid, item->args);
850 argv = __generate_argv(args);
852 pid = __fork_and_exec_with_args(argv, APPFW_UID);
859 static int __process_reinstall(pm_dbus_msg *item)
863 char args[MAX_PKG_ARGS_LEN];
866 backend_cmd = _get_backend_cmd(item->pkg_type);
867 if (backend_cmd == NULL)
870 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
871 item->req_id, item->pkgid, (int)item->uid);
872 argv = __generate_argv(args);
874 pid = __fork_and_exec_with_args(argv, APPFW_UID);
882 static int __process_uninstall(pm_dbus_msg *item)
886 char args[MAX_PKG_ARGS_LEN];
889 backend_cmd = _get_backend_cmd(item->pkg_type);
890 if (backend_cmd == NULL)
893 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
894 item->req_id, item->pkgid, (int)item->uid);
895 argv = __generate_argv(args);
897 pid = __fork_and_exec_with_args(argv, APPFW_UID);
905 static int __process_move(pm_dbus_msg *item)
909 char args[MAX_PKG_ARGS_LEN];
912 backend_cmd = _get_backend_cmd(item->pkg_type);
913 if (backend_cmd == NULL)
916 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
917 item->req_id, item->pkgid, (int)item->uid, item->args);
918 argv = __generate_argv(args);
920 pid = __fork_and_exec_with_args(argv, APPFW_UID);
928 static int __process_enable_pkg(pm_dbus_msg *item)
932 char args[MAX_PKG_ARGS_LEN];
935 backend_cmd = _get_backend_cmd(item->pkg_type);
936 if (backend_cmd == NULL)
939 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s", backend_cmd,
940 item->req_id, (int)item->uid, item->pkgid);
941 argv = __generate_argv(args);
943 pid = __fork_and_exec_with_args(argv, APPFW_UID);
951 static int __process_disable_pkg(pm_dbus_msg *item)
955 char args[MAX_PKG_ARGS_LEN];
958 backend_cmd = _get_backend_cmd(item->pkg_type);
959 if (backend_cmd == NULL)
962 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s", backend_cmd,
963 item->req_id, (int)item->uid, item->pkgid);
964 argv = __generate_argv(args);
966 pid = __fork_and_exec_with_args(argv, APPFW_UID);
974 static int __process_enable_app(pm_dbus_msg *item)
977 bool is_global = false;
979 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
980 PKGMGR_INSTALLER_START_KEY_STR,
981 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, item->req_type);
983 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
984 ret = __change_item_info(item, item->uid, &is_global);
985 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
986 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
987 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
992 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
993 if (ret != PMINFO_R_OK)
994 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
995 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
998 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
999 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1006 static int __process_disable_app(pm_dbus_msg *item)
1009 bool is_global = false;
1011 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1012 PKGMGR_INSTALLER_START_KEY_STR,
1013 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, item->req_type);
1015 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1016 ret = __change_item_info(item, item->uid, &is_global);
1017 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1018 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1019 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1024 ret = __kill_app(item->appid, item->uid);
1025 if (ret != PMINFO_R_OK) {
1026 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1027 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1031 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
1032 if (ret != PMINFO_R_OK)
1033 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1034 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1037 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1038 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1044 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
1047 bool is_global = true;
1049 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1050 PKGMGR_INSTALLER_START_KEY_STR,
1051 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID, item->req_type);
1053 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1054 ret = __change_item_info(item, item->uid, &is_global);
1055 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1056 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1057 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1062 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
1063 if (ret != PMINFO_R_OK)
1064 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1065 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1068 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1069 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1075 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
1078 bool is_global = true;
1080 __send_app_signal(item->uid, item->req_id,
1081 item->pkgid, item->pkgid,
1082 PKGMGR_INSTALLER_START_KEY_STR,
1083 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID, item->req_type);
1085 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1086 ret = __change_item_info(item, GLOBAL_USER, &is_global);
1087 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1088 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1089 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1094 ret = __kill_app(item->appid, item->uid);
1095 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid,
1098 if (ret != PMINFO_R_OK)
1099 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1100 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1103 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1104 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1110 static int __process_getsize(pm_dbus_msg *item)
1112 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1114 char args[MAX_PKG_ARGS_LEN];
1117 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1118 item->args, item->req_id);
1119 argv = __generate_argv(args);
1120 pid = __fork_and_exec_with_args(argv, item->uid);
1127 static int __process_cleardata(pm_dbus_msg *item)
1131 char args[MAX_PKG_ARGS_LEN];
1134 backend_cmd = _get_backend_cmd(item->pkg_type);
1135 if (backend_cmd == NULL)
1138 /* TODO: set movetype */
1139 snprintf(args, sizeof(args), "%s -k %s -c %s -u %d", backend_cmd,
1140 item->req_id, item->pkgid, (int)item->uid);
1141 argv = __generate_argv(args);
1143 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1151 static int __process_clearcache(pm_dbus_msg *item)
1153 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1155 char args[MAX_PKG_ARGS_LEN];
1158 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1159 argv = __generate_argv(args);
1160 pid = __fork_and_exec_with_args(argv, item->uid);
1167 static int __process_kill(pm_dbus_msg *item)
1170 pkgmgrinfo_pkginfo_h handle;
1171 pkgcmd_data *pdata = NULL;
1173 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1176 ERR("Failed to get handle");
1180 pdata = calloc(1, sizeof(pkgcmd_data));
1181 if (pdata == NULL) {
1182 ERR("memory alloc failed");
1185 pdata->cmd = strdup("kill");
1186 if (pdata->cmd == NULL) {
1187 ERR("out of memory");
1192 pdata->uid = item->uid;
1193 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1194 __pkgcmd_app_cb, pdata, item->uid);
1198 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1200 ERR("pkgmgrinfo_appinfo_get_list() failed");
1207 static int __process_check(pm_dbus_msg *item)
1210 pkgmgrinfo_pkginfo_h handle;
1211 pkgcmd_data *pdata = NULL;
1213 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1216 ERR("Failed to get handle");
1220 pdata = calloc(1, sizeof(pkgcmd_data));
1221 if (pdata == NULL) {
1222 ERR("memory alloc failed");
1225 pdata->cmd = strdup("check");
1226 if (pdata->cmd == NULL) {
1227 ERR("out of memory");
1232 pdata->uid = item->uid;
1233 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1234 __pkgcmd_app_cb, pdata, item->uid);
1238 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1240 ERR("pkgmgrinfo_appinfo_get_list() failed");
1247 static int __process_generate_license_request(pm_dbus_msg *item)
1251 char req_data[MAX_PKG_ARGS_LEN];
1252 unsigned int req_data_len;
1253 char license_url[MAX_PKG_ARGS_LEN];
1254 unsigned int license_url_len;
1256 resp_data = item->args;
1257 req_data_len = sizeof(req_data);
1258 license_url_len = sizeof(license_url);
1260 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1261 req_data, &req_data_len, license_url, &license_url_len);
1262 if (ret != TADC_SUCCESS) {
1263 ERR("drm_tizen_generate_license_request failed: %d", ret);
1264 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1265 PKGMGR_R_ESYSTEM, "", ""));
1269 __return_value_to_caller(item->req_id,
1270 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1276 static int __process_register_license(pm_dbus_msg *item)
1281 resp_data = item->args;
1283 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1284 if (ret != TADC_SUCCESS) {
1285 ERR("drm_tizen_register_license failed: %d", ret);
1286 __return_value_to_caller(item->req_id,
1287 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1291 __return_value_to_caller(item->req_id,
1292 g_variant_new("(i)", PKGMGR_R_OK));
1297 static int __process_decrypt_package(pm_dbus_msg *item)
1300 char *drm_file_path;
1301 char *decrypted_file_path;
1303 drm_file_path = item->pkgid;
1304 decrypted_file_path = item->args;
1306 /* TODO: check ownership of decrypted file */
1307 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1308 decrypted_file_path, strlen(decrypted_file_path));
1309 if (ret != TADC_SUCCESS) {
1310 ERR("drm_tizen_register_license failed: %d", ret);
1311 __return_value_to_caller(item->req_id,
1312 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1316 __return_value_to_caller(item->req_id,
1317 g_variant_new("(i)", PKGMGR_R_OK));
1322 static int __process_update_app_splash_screen(pm_dbus_msg *item, int flag)
1325 bool is_global = false;
1328 ret = __change_item_info(item, item->uid, &is_global);
1329 if (ret != PMINFO_R_OK || strlen(item->appid) == 0)
1332 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1333 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1334 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1335 PKGMGR_INSTALLER_START_KEY_STR, val, item->req_type);
1338 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
1339 item->appid, item->uid, flag);
1341 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1342 item->appid, item->uid, flag);
1343 if (ret != PMINFO_R_OK)
1344 __send_app_signal(item->uid, item->req_id, item->pkgid,
1345 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1346 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1349 __send_app_signal(item->uid, item->req_id, item->pkgid,
1350 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1351 PKGMGR_INSTALLER_OK_EVENT_STR,
1357 static int __process_set_restriction_mode(pm_dbus_msg *item)
1362 mode = atoi(item->args);
1363 ret = _restriction_mode_set(item->uid, item->pkgid, mode);
1365 __return_value_to_caller(item->req_id,
1366 g_variant_new("(i)", ret));
1371 static int __process_unset_restriction_mode(pm_dbus_msg *item)
1376 mode = atoi(item->args);
1377 ret = _restriction_mode_unset(item->uid, item->pkgid, mode);
1379 __return_value_to_caller(item->req_id,
1380 g_variant_new("(i)", ret));
1385 static int __process_get_restriction_mode(pm_dbus_msg *item)
1390 ret = _restriction_mode_get(item->uid, item->pkgid, &mode);
1392 __return_value_to_caller(item->req_id,
1393 g_variant_new("(ii)", mode, ret));
1398 gboolean queue_job(void *data)
1400 pm_dbus_msg *item = NULL;
1405 /* Pop a job from queue */
1406 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1407 if (__is_backend_busy(x))
1410 item = _pm_queue_pop(x);
1411 if (item && item->req_type != -1)
1416 /* all backend messages queue are empty or busy */
1417 if (x == num_of_backends)
1420 /*save pkg type and pkg name for future*/
1421 strncpy(ptr->req_id, item->req_id, MAX_REQ_ID_LEN - 1);
1422 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN - 1);
1423 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN - 1);
1424 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN - 1);
1425 memset((item->appid), 0, MAX_PKG_NAME_LEN);
1426 ptr->uid = item->uid;
1427 ptr->req_type = item->req_type;
1428 DBG("handle request type [%d]", item->req_type);
1430 switch (item->req_type) {
1431 case PKGMGR_REQUEST_TYPE_INSTALL:
1432 __set_backend_busy(x);
1433 ret = __process_install(item);
1435 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
1436 __set_backend_busy(x);
1437 ret = __process_mount_install(item);
1439 case PKGMGR_REQUEST_TYPE_REINSTALL:
1440 __set_backend_busy(x);
1441 ret = __process_reinstall(item);
1443 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1444 __set_backend_busy(x);
1445 ret = __process_uninstall(item);
1447 case PKGMGR_REQUEST_TYPE_MOVE:
1448 __set_backend_busy(x);
1449 ret = __process_move(item);
1451 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1452 ret = __process_enable_pkg(item);
1454 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1455 ret = __process_disable_pkg(item);
1457 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1458 ret = __process_enable_app(item);
1460 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1461 ret = __process_disable_app(item);
1463 case PKGMGR_REQUEST_TYPE_GETSIZE:
1464 __set_backend_busy(x);
1465 ret = __process_getsize(item);
1467 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1468 __set_backend_busy(x);
1469 ret = __process_cleardata(item);
1471 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1472 __set_backend_busy(x);
1473 ret = __process_clearcache(item);
1475 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1476 ret = __process_enable_global_app_for_uid(item);
1478 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1479 ret = __process_disable_global_app_for_uid(item);
1481 case PKGMGR_REQUEST_TYPE_KILL:
1482 ret = __process_kill(item);
1484 case PKGMGR_REQUEST_TYPE_CHECK:
1485 ret = __process_check(item);
1487 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1488 ret = __process_generate_license_request(item);
1490 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1491 ret = __process_register_license(item);
1493 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1494 ret = __process_decrypt_package(item);
1496 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1497 ret = __process_update_app_splash_screen(item, 1);
1499 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1500 ret = __process_update_app_splash_screen(item, 0);
1502 case PKGMGR_REQUEST_TYPE_SET_RESTRICTION_MODE:
1503 ret = __process_set_restriction_mode(item);
1505 case PKGMGR_REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1506 ret = __process_unset_restriction_mode(item);
1508 case PKGMGR_REQUEST_TYPE_GET_RESTRICTION_MODE:
1509 ret = __process_get_restriction_mode(item);
1522 #define IS_WHITESPACE(CHAR) \
1523 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1525 void _app_str_trim(char *input)
1527 char *trim_str = input;
1532 while (*input != 0) {
1533 if (!IS_WHITESPACE(*input)) {
1544 char *_get_backend_cmd(char *type)
1547 char buffer[1024] = { 0 };
1548 char *command = NULL;
1551 fp = fopen(PKG_CONF_PATH, "r");
1556 while (fgets(buffer, 1024, fp) != NULL) {
1557 if (buffer[0] == '#')
1560 _app_str_trim(buffer);
1562 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1563 DBG("buffer [%s]", buffer);
1564 path = path + strlen(PKG_BACKEND);
1565 DBG("path [%s]", path);
1568 (char *)malloc(sizeof(char) * strlen(path) +
1570 if (command == NULL) {
1575 size = strlen(path) + strlen(type) + 1;
1576 snprintf(command, size, "%s%s", path, type);
1577 command[strlen(path) + strlen(type)] = '\0';
1578 DBG("command [%s]", command);
1586 memset(buffer, 0x00, 1024);
1592 return NULL; /* cannot find proper command */
1595 int main(int argc, char *argv[])
1599 DBG("server start");
1601 r = _pm_queue_init();
1603 DBG("Queue Initialization Failed\n");
1607 r = __init_backend_info();
1609 DBG("backend info init failed");
1613 r = __init_request_handler();
1615 ERR("dbus init failed");
1619 if (__register_signal_handler()) {
1620 ERR("failed to register signal handler");
1624 #if !GLIB_CHECK_VERSION(2, 35, 0)
1627 mainloop = g_main_loop_new(NULL, FALSE);
1629 ERR("g_main_loop_new failed");
1633 DBG("Main loop is created.");
1635 g_main_loop_run(mainloop);
1637 DBG("Quit main loop.");
1638 __fini_request_handler();
1639 __fini_backend_info();
1642 DBG("package manager server terminated.");