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)
57 #define EXT_STORAGE_GROUP 10001
58 #define EXT_STORAGE_APPDATA_GROUP 10002
59 #define MEDIA_STORAGE_GROUP 10502
60 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
74 8 bit value to represent maximum 8 backends.
75 Each bit position corresponds to a queue slot which
76 is dynamically determined.
78 char backend_busy = 0;
79 extern int num_of_backends;
81 struct signal_info_t {
86 static int pipe_sig[2];
87 static GIOChannel *pipe_io;
88 static guint pipe_wid;
91 extern queue_info_map *start;
94 GMainLoop *mainloop = NULL;
99 OPERATION_INSTALL = 0,
106 static int __check_backend_status_for_exit(void);
107 static int __check_queue_status_for_exit(void);
108 static int __is_backend_busy(int position);
109 static void __set_backend_busy(int position);
110 static void __set_backend_free(int position);
111 static void sighandler(int signo);
113 gboolean exit_server(void *data);
115 /* To check whether a particular backend is free/busy*/
116 static int __is_backend_busy(int position)
118 return backend_busy & 1<<position;
120 /*To set a particular backend as busy*/
121 static void __set_backend_busy(int position)
123 backend_busy = backend_busy | 1<<position;
125 /*To set a particular backend as free */
126 static void __set_backend_free(int position)
128 backend_busy = backend_busy & ~(1<<position);
131 static void __send_app_signal(uid_t uid, const char *req_id,
132 const char *pkgid, const char *appid,
133 const char *key, const char *val, int req_type)
135 pkgmgr_installer *pi;
137 pi = pkgmgr_installer_new();
139 DBG("Failure in creating the pkgmgr_installer object");
143 if (pkgmgr_installer_set_uid(pi, uid))
147 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
148 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
149 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP))
152 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
153 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
154 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP))
157 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
158 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN))
161 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
162 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN))
166 DBG("Unsupported req_type[%d]", req_type);
170 if (pkgmgr_installer_set_session_id(pi, req_id))
172 pkgmgr_installer_send_app_signal(pi, "app", pkgid, appid, key, val);
175 pkgmgr_installer_free(pi);
180 static void __send_fail_signal(backend_info *info)
183 pkgmgr_installer *pi;
184 pi = pkgmgr_installer_new();
186 ERR("Failure in creating the pkgmgr_installer object");
189 pkgmgr_installer_set_session_id(pi, info->req_id);
190 switch(info->req_type) {
191 case PKGMGR_REQUEST_TYPE_INSTALL:
192 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
193 case PKGMGR_REQUEST_TYPE_REINSTALL:
194 req_type = PKGMGR_REQ_INSTALL;
196 case PKGMGR_REQUEST_TYPE_UNINSTALL:
197 req_type = PKGMGR_REQ_UNINSTALL;
199 case PKGMGR_REQUEST_TYPE_MOVE:
200 req_type = PKGMGR_REQ_MOVE;
202 case PKGMGR_REQUEST_TYPE_GETSIZE:
203 req_type = PKGMGR_REQ_GETSIZE;
206 req_type = PKGMGR_REQ_INVALID;
209 pkgmgr_installer_set_request_type(pi, req_type);
210 pkgmgr_installer_send_signal(pi, info->pkgtype, info->pkgid, "end", "fail");
211 pkgmgr_installer_free(pi);
215 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
221 struct signal_info_t info;
222 backend_info *ptr = begin;
224 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
225 if (s != G_IO_STATUS_NORMAL) {
226 ERR("Signal pipe read failed: %s", err->message);
231 for (x = 0; x < num_of_backends; x++, ptr++) {
232 if (ptr && ptr->pid == info.pid)
236 if (x == num_of_backends) {
237 ERR("Unknown child exit");
241 __set_backend_free(x);
242 if (WIFSIGNALED(info.status)) {
243 __send_fail_signal(ptr);
244 DBG("backend[%s] exit with signal[%d]", ptr->pkgtype,
245 WTERMSIG(info.status));
246 } else if (WEXITSTATUS(info.status)) {
247 DBG("backend[%s] exit with error", ptr->pkgtype);
249 DBG("backend[%s] exit", ptr->pkgtype);
252 g_idle_add(queue_job, NULL);
257 static int __init_backend_info(void)
261 /*Allocate memory for holding pid, pkgtype and pkgid*/
262 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
264 DBG("Malloc Failed\n");
269 if (pipe(pipe_sig)) {
270 ERR("create pipe failed");
274 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
275 g_io_channel_set_encoding(pipe_io, NULL, NULL);
276 g_io_channel_set_buffered(pipe_io, FALSE);
277 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
282 static void __fini_backend_info(void)
284 g_source_remove(pipe_wid);
285 g_io_channel_unref(pipe_io);
289 /*Free backend info */
293 static void sighandler(int signo)
295 struct signal_info_t info;
296 char buf[1024] = {0, };
298 info.pid = waitpid(-1, &info.status, WNOHANG);
299 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
300 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
303 static int __register_signal_handler(void)
305 static int sig_reg = 0;
306 struct sigaction act;
311 act.sa_handler = sighandler;
312 sigemptyset(&act.sa_mask);
313 act.sa_flags = SA_NOCLDSTOP;
314 if (sigaction(SIGCHLD, &act, NULL) < 0) {
315 ERR("signal: SIGCHLD failed\n");
319 g_timeout_add_seconds(2, exit_server, NULL);
325 static int __check_backend_status_for_exit(void)
328 for(i = 0; i < num_of_backends; i++)
330 if (!__is_backend_busy(i))
338 static int __check_queue_status_for_exit(void)
340 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
341 queue_info_map *ptr = NULL;
346 for(i = 0; i < entries; i++)
348 if (ptr->queue_slot <= slot) {
354 slot = ptr->queue_slot;
359 for(i = 0; i < num_of_backends; i++)
369 gboolean exit_server(void *data)
371 DBG("exit_server Start\n");
372 if (__check_backend_status_for_exit() &&
373 __check_queue_status_for_exit()) {
374 if (!getenv("PMS_STANDALONE")) {
375 g_main_loop_quit(mainloop);
382 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
386 if (buf == NULL || path == NULL)
388 fd = open(path, O_RDONLY);
391 ret = read(fd, buf, size - 1);
401 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
402 const char *cmdline, const char *apppath)
407 if (strcmp(cmdline, apppath) == 0) {
411 ERR("getpgid failed, errno(%d)", errno);
420 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
423 struct dirent dentry, *result;
426 char buf[1024] = {'\0'};
429 dp = opendir("/proc");
434 for (ret = readdir_r(dp, &dentry, &result);
435 ret == 0 && result != NULL;
436 ret = readdir_r(dp, &dentry, &result)) {
437 if (!isdigit(dentry.d_name[0]))
440 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
441 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
445 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
454 ERR("getpgid failed, errno(%d)", errno);
457 if (killpg(pgid, SIGKILL) < 0) {
459 ERR("killpg failed, errno(%d)", errno);
470 static void __make_pid_info_file(char *req_key, int pid, uid_t uid)
475 char buf[MAX_PKG_TYPE_LEN] = {0};
476 char info_file[PATH_MAX] = {'\0'};
478 struct passwd *pwd_result;
483 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
484 if (ret != 0 || pwd_result == NULL) {
485 ERR("get uid failed(%d) for user(%d)", ret, uid);
488 DBG("uid(%d), gid(%d)", uid, pwd.pw_gid);
490 snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
492 DBG("info_path(%s)", info_file);
493 file = fopen(info_file, "w");
495 ERR("Couldn't open the file(%s)", info_file);
499 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
500 fwrite(buf, 1, strlen(buf), file);
504 if (fchmod(fd, 0777) < 0)
505 ERR("chmod failed, errno(%d)", errno);
506 if (fchown(fd, uid, pwd.pw_gid) < 0)
507 ERR("chown failed, errno(%d)", errno);
512 static int __kill_app(char *appid, uid_t uid)
514 pkgmgrinfo_appinfo_h appinfo;
515 int ret = PMINFO_R_ERROR;
518 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
519 if (ret != PMINFO_R_OK)
520 return PMINFO_R_ERROR;
522 ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
523 if (ret != PMINFO_R_OK) {
524 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
525 return PMINFO_R_ERROR;
528 ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
529 if (ret != PMINFO_R_OK) {
530 DBG("failed to kill app[%s], exec[%s]", appid, exec);
533 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
537 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
543 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
545 if (handle == NULL) {
546 perror("appinfo handle is NULL\n");
549 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
551 perror("Failed to get app exec path\n");
554 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
556 perror("Failed to get pkgid\n");
560 if (strcmp(pdata->cmd, "kill") == 0)
561 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
562 else if(strcmp(pdata->cmd, "check") == 0)
563 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
565 __make_pid_info_file(pkgid, pid, pdata->uid);
570 void free_user_context(user_ctx* ctx)
577 //env variable ends by NULL element
587 int set_environement(user_ctx *ctx)
592 gid_t groups[] = {EXT_STORAGE_GROUP,
593 EXT_STORAGE_APPDATA_GROUP,
594 MEDIA_STORAGE_GROUP};
598 if (setgid(ctx->gid)) {
599 ERR("setgid failed: %d", errno);
602 if (setgroups(ARRAY_SIZE(groups), groups) < 0) {
603 ERR("setgroups failed: %d", errno);
606 if (setuid(ctx->uid)) {
607 ERR("setuid failed: %d", errno);
611 //env variable ends by NULL element
613 if (putenv(env[i]) != 0)
620 user_ctx *get_user_context(uid_t uid)
622 /* we can use getpwnam because this is used only after a
623 * fork and just before an execv
624 * No concurrencial call can corrupt the data
625 * returned by getpwuid
627 user_ctx *context_res;
629 char buf[1024] = {0, };
630 struct passwd pwd, *result;
635 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
636 if (ret != 0 || result == NULL)
640 context_res = (user_ctx *)malloc(sizeof(user_ctx));
645 env = (char **)malloc(3 * sizeof(char *));
650 // Build environment context
651 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
652 env[0] = (char *)malloc((len + 1) * sizeof(char));
657 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
658 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
659 env[1] = (char *)malloc((len + 1) * sizeof(char));
664 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
672 //env variable ends by NULL element
673 while (env && env[i]) {
680 context_res->env = env;
681 context_res->uid = uid;
682 context_res->gid = pwd.pw_gid;
687 static char **__generate_argv(const char *args)
689 /* Create args vector
690 * req_id + pkgid + args
692 * vector size = # of args +
693 *(req_id + pkgid + NULL termination = 3)
694 * Last value must be NULL for execv.
702 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
703 if (FALSE == ret_parse) {
704 DBG("Failed to split args: %s", args);
705 DBG("messsage: %s", gerr->message);
710 for (i = 0; i < argcp; i++)
711 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
716 void __set_environment(gpointer user_data)
718 user_ctx *ctx = (user_ctx *)user_data;
720 if (set_environement(ctx))
721 DBG("Failed to set env for the user : %d", ctx->uid);
724 static int __fork_and_exec_with_args(char **argv, uid_t uid)
726 user_ctx* user_context;
727 GError *error = NULL;
731 user_context = get_user_context(uid);
733 DBG("Failed to getenv for the user : %d", uid);
737 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
738 __set_environment, (gpointer)user_context, &pid,
741 ERR("Failed to excute backend: %s", error->message);
745 free_user_context(user_context);
750 static int __change_item_info(pm_dbus_msg *item, uid_t uid, bool *is_global)
754 pkgmgrinfo_appinfo_h handle = NULL;
756 switch (item->req_type) {
757 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
758 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
759 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
760 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
761 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
763 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
764 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
765 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
768 return PMINFO_R_ERROR;
771 if (ret != PMINFO_R_OK)
772 return PMINFO_R_ERROR;
774 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
775 if (ret != PMINFO_R_OK)
778 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
779 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
781 ret = PMINFO_R_ERROR;
783 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
784 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
786 ret = PMINFO_R_ERROR;
790 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
791 if (ret != PMINFO_R_OK)
794 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
795 memset((item->pkgid), 0, MAX_PKG_NAME_LEN);
796 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
799 pkgmgrinfo_appinfo_destroy_appinfo(handle);
804 static int __process_install(pm_dbus_msg *item)
808 char args[MAX_PKG_ARGS_LEN] = {'\0', };
811 backend_cmd = _get_backend_cmd(item->pkg_type);
812 if (backend_cmd == NULL)
815 snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd,
816 item->req_id, item->pkgid, item->args);
818 argv = __generate_argv(args);
820 pid = __fork_and_exec_with_args(argv, item->uid);
827 static int __process_mount_install(pm_dbus_msg *item)
831 char args[MAX_PKG_ARGS_LEN] = {'\0', };
834 backend_cmd = _get_backend_cmd(item->pkg_type);
835 if (backend_cmd == NULL)
838 snprintf(args, sizeof(args), "%s -k %s -w %s %s", backend_cmd,
839 item->req_id, item->pkgid, item->args);
841 argv = __generate_argv(args);
843 pid = __fork_and_exec_with_args(argv, item->uid);
850 static int __process_reinstall(pm_dbus_msg *item)
854 char args[MAX_PKG_ARGS_LEN];
857 backend_cmd = _get_backend_cmd(item->pkg_type);
858 if (backend_cmd == NULL)
861 snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
862 item->req_id, item->pkgid);
863 argv = __generate_argv(args);
865 pid = __fork_and_exec_with_args(argv, item->uid);
873 static int __process_uninstall(pm_dbus_msg *item)
877 char args[MAX_PKG_ARGS_LEN];
880 backend_cmd = _get_backend_cmd(item->pkg_type);
881 if (backend_cmd == NULL)
884 snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
885 item->req_id, item->pkgid);
886 argv = __generate_argv(args);
888 pid = __fork_and_exec_with_args(argv, item->uid);
896 static int __process_move(pm_dbus_msg *item)
900 char args[MAX_PKG_ARGS_LEN];
903 backend_cmd = _get_backend_cmd(item->pkg_type);
904 if (backend_cmd == NULL)
907 snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
908 item->req_id, item->pkgid, item->args);
909 argv = __generate_argv(args);
911 pid = __fork_and_exec_with_args(argv, item->uid);
919 static int __process_enable_pkg(pm_dbus_msg *item)
923 char args[MAX_PKG_ARGS_LEN];
926 backend_cmd = _get_backend_cmd(item->pkg_type);
927 if (backend_cmd == NULL)
930 snprintf(args, sizeof(args), "%s -k %s -A %s", backend_cmd,
931 item->req_id, item->pkgid);
932 argv = __generate_argv(args);
934 pid = __fork_and_exec_with_args(argv, item->uid);
942 static int __process_disable_pkg(pm_dbus_msg *item)
946 char args[MAX_PKG_ARGS_LEN];
949 backend_cmd = _get_backend_cmd(item->pkg_type);
950 if (backend_cmd == NULL)
953 snprintf(args, sizeof(args), "%s -k %s -D %s", backend_cmd,
954 item->req_id, item->pkgid);
955 argv = __generate_argv(args);
957 pid = __fork_and_exec_with_args(argv, item->uid);
965 static int __process_enable_app(pm_dbus_msg *item)
968 bool is_global = false;
970 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
971 PKGMGR_INSTALLER_START_KEY_STR,
972 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, item->req_type);
974 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
975 ret = __change_item_info(item, item->uid, &is_global);
976 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
977 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
978 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
983 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
984 if (ret != PMINFO_R_OK)
985 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
986 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
989 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
990 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
997 static int __process_disable_app(pm_dbus_msg *item)
1000 bool is_global = false;
1002 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1003 PKGMGR_INSTALLER_START_KEY_STR,
1004 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, item->req_type);
1006 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1007 ret = __change_item_info(item, item->uid, &is_global);
1008 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1009 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1010 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1015 ret = __kill_app(item->appid, item->uid);
1016 if (ret != PMINFO_R_OK) {
1017 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1018 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1022 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
1023 if (ret != PMINFO_R_OK)
1024 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1025 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1028 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1029 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1035 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
1038 bool is_global = true;
1040 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1041 PKGMGR_INSTALLER_START_KEY_STR,
1042 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID, item->req_type);
1044 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1045 ret = __change_item_info(item, item->uid, &is_global);
1046 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1047 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1048 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1053 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
1054 if (ret != PMINFO_R_OK)
1055 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1056 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1059 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1060 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1066 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
1069 bool is_global = true;
1071 __send_app_signal(item->uid, item->req_id,
1072 item->pkgid, item->pkgid,
1073 PKGMGR_INSTALLER_START_KEY_STR,
1074 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID, item->req_type);
1076 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1077 ret = __change_item_info(item, GLOBAL_USER, &is_global);
1078 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1079 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1080 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1085 ret = __kill_app(item->appid, item->uid);
1086 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid,
1089 if (ret != PMINFO_R_OK)
1090 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1091 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1094 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1095 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1101 static int __process_getsize(pm_dbus_msg *item)
1103 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1105 char args[MAX_PKG_ARGS_LEN];
1108 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1109 item->args, item->req_id);
1110 argv = __generate_argv(args);
1111 pid = __fork_and_exec_with_args(argv, item->uid);
1118 static int __process_cleardata(pm_dbus_msg *item)
1122 char args[MAX_PKG_ARGS_LEN];
1125 backend_cmd = _get_backend_cmd(item->pkg_type);
1126 if (backend_cmd == NULL)
1129 /* TODO: set movetype */
1130 snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
1131 item->req_id, item->pkgid);
1132 argv = __generate_argv(args);
1134 pid = __fork_and_exec_with_args(argv, item->uid);
1142 static int __process_clearcache(pm_dbus_msg *item)
1144 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1146 char args[MAX_PKG_ARGS_LEN];
1149 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1150 argv = __generate_argv(args);
1151 pid = __fork_and_exec_with_args(argv, item->uid);
1158 static int __process_kill(pm_dbus_msg *item)
1161 pkgmgrinfo_pkginfo_h handle;
1162 pkgcmd_data *pdata = NULL;
1164 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1167 ERR("Failed to get handle");
1171 pdata = calloc(1, sizeof(pkgcmd_data));
1172 if (pdata == NULL) {
1173 ERR("memory alloc failed");
1176 pdata->cmd = strdup("kill");
1177 if (pdata->cmd == NULL) {
1178 ERR("out of memory");
1183 pdata->uid = item->uid;
1184 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1185 __pkgcmd_app_cb, pdata, item->uid);
1189 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1191 ERR("pkgmgrinfo_appinfo_get_list() failed");
1198 static int __process_check(pm_dbus_msg *item)
1201 pkgmgrinfo_pkginfo_h handle;
1202 pkgcmd_data *pdata = NULL;
1204 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1207 ERR("Failed to get handle");
1211 pdata = calloc(1, sizeof(pkgcmd_data));
1212 if (pdata == NULL) {
1213 ERR("memory alloc failed");
1216 pdata->cmd = strdup("check");
1217 if (pdata->cmd == NULL) {
1218 ERR("out of memory");
1223 pdata->uid = item->uid;
1224 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1225 __pkgcmd_app_cb, pdata, item->uid);
1229 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1231 ERR("pkgmgrinfo_appinfo_get_list() failed");
1238 static int __process_generate_license_request(pm_dbus_msg *item)
1242 char req_data[MAX_PKG_ARGS_LEN];
1243 unsigned int req_data_len;
1244 char license_url[MAX_PKG_ARGS_LEN];
1245 unsigned int license_url_len;
1247 resp_data = item->args;
1248 req_data_len = sizeof(req_data);
1249 license_url_len = sizeof(license_url);
1251 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1252 req_data, &req_data_len, license_url, &license_url_len);
1253 if (ret != TADC_SUCCESS) {
1254 ERR("drm_tizen_generate_license_request failed: %d", ret);
1255 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1256 PKGMGR_R_ESYSTEM, "", ""));
1260 __return_value_to_caller(item->req_id,
1261 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1267 static int __process_register_license(pm_dbus_msg *item)
1272 resp_data = item->args;
1274 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1275 if (ret != TADC_SUCCESS) {
1276 ERR("drm_tizen_register_license failed: %d", ret);
1277 __return_value_to_caller(item->req_id,
1278 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1282 __return_value_to_caller(item->req_id,
1283 g_variant_new("(i)", PKGMGR_R_OK));
1288 static int __process_decrypt_package(pm_dbus_msg *item)
1291 char *drm_file_path;
1292 char *decrypted_file_path;
1294 drm_file_path = item->pkgid;
1295 decrypted_file_path = item->args;
1297 /* TODO: check ownership of decrypted file */
1298 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1299 decrypted_file_path, strlen(decrypted_file_path));
1300 if (ret != TADC_SUCCESS) {
1301 ERR("drm_tizen_register_license failed: %d", ret);
1302 __return_value_to_caller(item->req_id,
1303 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1307 __return_value_to_caller(item->req_id,
1308 g_variant_new("(i)", PKGMGR_R_OK));
1313 static int __process_update_app_splash_screen(pm_dbus_msg *item, int flag)
1316 bool is_global = false;
1319 ret = __change_item_info(item, item->uid, &is_global);
1320 if (ret != PMINFO_R_OK || strlen(item->appid) == 0)
1323 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1324 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1325 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1326 PKGMGR_INSTALLER_START_KEY_STR, val, item->req_type);
1329 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
1330 item->appid, item->uid, flag);
1332 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1333 item->appid, item->uid, flag);
1334 if (ret != PMINFO_R_OK)
1335 __send_app_signal(item->uid, item->req_id, item->pkgid,
1336 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1337 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1340 __send_app_signal(item->uid, item->req_id, item->pkgid,
1341 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1342 PKGMGR_INSTALLER_OK_EVENT_STR,
1348 static int __process_set_restriction_mode(pm_dbus_msg *item)
1353 mode = atoi(item->args);
1354 ret = _restriction_mode_set(item->uid, item->pkgid, mode);
1356 __return_value_to_caller(item->req_id,
1357 g_variant_new("(i)", ret));
1362 static int __process_unset_restriction_mode(pm_dbus_msg *item)
1367 mode = atoi(item->args);
1368 ret = _restriction_mode_unset(item->uid, item->pkgid, mode);
1370 __return_value_to_caller(item->req_id,
1371 g_variant_new("(i)", ret));
1376 static int __process_get_restriction_mode(pm_dbus_msg *item)
1381 ret = _restriction_mode_get(item->uid, item->pkgid, &mode);
1383 __return_value_to_caller(item->req_id,
1384 g_variant_new("(ii)", mode, ret));
1389 gboolean queue_job(void *data)
1391 pm_dbus_msg *item = NULL;
1396 /* Pop a job from queue */
1397 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1398 if (__is_backend_busy(x))
1401 item = _pm_queue_pop(x);
1402 if (item && item->req_type != -1)
1407 /* all backend messages queue are empty or busy */
1408 if (x == num_of_backends)
1411 /*save pkg type and pkg name for future*/
1412 strncpy(ptr->req_id, item->req_id, MAX_REQ_ID_LEN - 1);
1413 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN - 1);
1414 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN - 1);
1415 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN - 1);
1416 memset((item->appid), 0, MAX_PKG_NAME_LEN);
1417 ptr->uid = item->uid;
1418 ptr->req_type = item->req_type;
1419 DBG("handle request type [%d]", item->req_type);
1421 switch (item->req_type) {
1422 case PKGMGR_REQUEST_TYPE_INSTALL:
1423 __set_backend_busy(x);
1424 ret = __process_install(item);
1426 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
1427 __set_backend_busy(x);
1428 ret = __process_mount_install(item);
1430 case PKGMGR_REQUEST_TYPE_REINSTALL:
1431 __set_backend_busy(x);
1432 ret = __process_reinstall(item);
1434 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1435 __set_backend_busy(x);
1436 ret = __process_uninstall(item);
1438 case PKGMGR_REQUEST_TYPE_MOVE:
1439 __set_backend_busy(x);
1440 ret = __process_move(item);
1442 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1443 ret = __process_enable_pkg(item);
1445 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1446 ret = __process_disable_pkg(item);
1448 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1449 ret = __process_enable_app(item);
1451 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1452 ret = __process_disable_app(item);
1454 case PKGMGR_REQUEST_TYPE_GETSIZE:
1455 __set_backend_busy(x);
1456 ret = __process_getsize(item);
1458 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1459 __set_backend_busy(x);
1460 ret = __process_cleardata(item);
1462 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1463 __set_backend_busy(x);
1464 ret = __process_clearcache(item);
1466 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1467 ret = __process_enable_global_app_for_uid(item);
1469 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1470 ret = __process_disable_global_app_for_uid(item);
1472 case PKGMGR_REQUEST_TYPE_KILL:
1473 ret = __process_kill(item);
1475 case PKGMGR_REQUEST_TYPE_CHECK:
1476 ret = __process_check(item);
1478 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1479 ret = __process_generate_license_request(item);
1481 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1482 ret = __process_register_license(item);
1484 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1485 ret = __process_decrypt_package(item);
1487 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1488 ret = __process_update_app_splash_screen(item, 1);
1490 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1491 ret = __process_update_app_splash_screen(item, 0);
1493 case PKGMGR_REQUEST_TYPE_SET_RESTRICTION_MODE:
1494 ret = __process_set_restriction_mode(item);
1496 case PKGMGR_REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1497 ret = __process_unset_restriction_mode(item);
1499 case PKGMGR_REQUEST_TYPE_GET_RESTRICTION_MODE:
1500 ret = __process_get_restriction_mode(item);
1513 #define IS_WHITESPACE(CHAR) \
1514 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1516 void _app_str_trim(char *input)
1518 char *trim_str = input;
1523 while (*input != 0) {
1524 if (!IS_WHITESPACE(*input)) {
1535 char *_get_backend_cmd(char *type)
1538 char buffer[1024] = { 0 };
1539 char *command = NULL;
1541 fp = fopen(PKG_CONF_PATH, "r");
1547 while (fgets(buffer, 1024, fp) != NULL) {
1548 if (buffer[0] == '#')
1551 _app_str_trim(buffer);
1553 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1554 DBG("buffer [%s]", buffer);
1555 path = path + strlen(PKG_BACKEND);
1556 DBG("path [%s]", path);
1559 (char *)malloc(sizeof(char) * strlen(path) +
1561 if (command == NULL) {
1566 size = strlen(path) + strlen(type) + 1;
1567 snprintf(command, size, "%s%s", path, type);
1568 command[strlen(path) + strlen(type)] = '\0';
1569 DBG("command [%s]", command);
1577 memset(buffer, 0x00, 1024);
1583 return NULL; /* cannot find proper command */
1586 int main(int argc, char *argv[])
1590 DBG("server start");
1592 r = _pm_queue_init();
1594 DBG("Queue Initialization Failed\n");
1598 r = __init_backend_info();
1600 DBG("backend info init failed");
1604 r = __init_request_handler();
1606 ERR("dbus init failed");
1610 if (__register_signal_handler()) {
1611 ERR("failed to register signal handler");
1615 #if !GLIB_CHECK_VERSION(2,35,0)
1618 mainloop = g_main_loop_new(NULL, FALSE);
1620 ERR("g_main_loop_new failed");
1624 DBG("Main loop is created.");
1626 g_main_loop_run(mainloop);
1628 DBG("Quit main loop.");
1629 __fini_request_handler();
1630 __fini_backend_info();
1633 DBG("package manager server terminated.");