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 #include <csr-content-screening.h>
47 #include "pkgmgr_installer.h"
48 #include "pkgmgr-server.h"
50 #include "package-manager.h"
53 #define NO_MATCHING_FILE 11
56 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
60 #define EXT_STORAGE_GROUP 10001
61 #define EXT_STORAGE_APPDATA_GROUP 10002
62 #define MEDIA_STORAGE_GROUP 10502
63 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
77 8 bit value to represent maximum 8 backends.
78 Each bit position corresponds to a queue slot which
79 is dynamically determined.
81 char backend_busy = 0;
82 extern int num_of_backends;
84 struct signal_info_t {
89 static int pipe_sig[2];
90 static GIOChannel *pipe_io;
91 static guint pipe_wid;
94 extern queue_info_map *start;
97 GMainLoop *mainloop = NULL;
102 OPERATION_INSTALL = 0,
109 static int __check_backend_status_for_exit(void);
110 static int __check_queue_status_for_exit(void);
111 static int __is_backend_busy(int position);
112 static void __set_backend_busy(int position);
113 static void __set_backend_free(int position);
114 static void sighandler(int signo);
116 gboolean exit_server(void *data);
118 /* To check whether a particular backend is free/busy*/
119 static int __is_backend_busy(int position)
121 return backend_busy & 1<<position;
123 /*To set a particular backend as busy*/
124 static void __set_backend_busy(int position)
126 backend_busy = backend_busy | 1<<position;
128 /*To set a particular backend as free */
129 static void __set_backend_free(int position)
131 backend_busy = backend_busy & ~(1<<position);
134 static void __send_app_signal(uid_t uid, const char *req_id,
135 const char *pkgid, const char *appid,
136 const char *key, const char *val, int req_type)
138 pkgmgr_installer *pi;
140 pi = pkgmgr_installer_new();
142 DBG("Failure in creating the pkgmgr_installer object");
146 if (pkgmgr_installer_set_uid(pi, uid))
150 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
151 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
152 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP))
155 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
156 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
157 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP))
160 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
161 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN))
164 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
165 if (pkgmgr_installer_set_request_type(pi, PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN))
169 DBG("Unsupported req_type[%d]", req_type);
173 if (pkgmgr_installer_set_session_id(pi, req_id))
175 pkgmgr_installer_send_app_signal(pi, "app", pkgid, appid, key, val);
178 pkgmgr_installer_free(pi);
183 static void __send_fail_signal(backend_info *info)
186 pkgmgr_installer *pi;
187 pi = pkgmgr_installer_new();
189 ERR("Failure in creating the pkgmgr_installer object");
192 pkgmgr_installer_set_session_id(pi, info->req_id);
193 switch (info->req_type) {
194 case PKGMGR_REQUEST_TYPE_INSTALL:
195 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
196 case PKGMGR_REQUEST_TYPE_REINSTALL:
197 req_type = PKGMGR_REQ_INSTALL;
199 case PKGMGR_REQUEST_TYPE_UNINSTALL:
200 req_type = PKGMGR_REQ_UNINSTALL;
202 case PKGMGR_REQUEST_TYPE_MOVE:
203 req_type = PKGMGR_REQ_MOVE;
205 case PKGMGR_REQUEST_TYPE_GETSIZE:
206 req_type = PKGMGR_REQ_GETSIZE;
209 req_type = PKGMGR_REQ_INVALID;
212 pkgmgr_installer_set_request_type(pi, req_type);
213 pkgmgr_installer_send_signal(pi, info->pkgtype, info->pkgid, "end", "fail");
214 pkgmgr_installer_free(pi);
218 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
224 struct signal_info_t info;
225 backend_info *ptr = begin;
227 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
228 if (s != G_IO_STATUS_NORMAL) {
229 ERR("Signal pipe read failed: %s", err->message);
234 for (x = 0; x < num_of_backends; x++, ptr++) {
235 if (ptr && ptr->pid == info.pid)
239 if (x == num_of_backends) {
240 ERR("Unknown child exit");
244 __set_backend_free(x);
245 if (WIFSIGNALED(info.status)) {
246 __send_fail_signal(ptr);
247 DBG("backend[%s] exit with signal[%d]", ptr->pkgtype,
248 WTERMSIG(info.status));
249 } else if (WEXITSTATUS(info.status)) {
250 DBG("backend[%s] exit with error", ptr->pkgtype);
252 DBG("backend[%s] exit", ptr->pkgtype);
255 g_idle_add(queue_job, NULL);
260 static int __init_backend_info(void)
264 /*Allocate memory for holding pid, pkgtype and pkgid*/
265 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
267 DBG("Malloc Failed\n");
272 if (pipe(pipe_sig)) {
273 ERR("create pipe failed");
277 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
278 g_io_channel_set_encoding(pipe_io, NULL, NULL);
279 g_io_channel_set_buffered(pipe_io, FALSE);
280 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
285 static void __fini_backend_info(void)
287 g_source_remove(pipe_wid);
288 g_io_channel_unref(pipe_io);
292 /*Free backend info */
296 static void sighandler(int signo)
298 struct signal_info_t info;
299 char buf[1024] = {0, };
301 info.pid = waitpid(-1, &info.status, WNOHANG);
302 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
303 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
306 static int __register_signal_handler(void)
308 static int sig_reg = 0;
309 struct sigaction act;
314 act.sa_handler = sighandler;
315 sigemptyset(&act.sa_mask);
316 act.sa_flags = SA_NOCLDSTOP;
317 if (sigaction(SIGCHLD, &act, NULL) < 0) {
318 ERR("signal: SIGCHLD failed\n");
322 g_timeout_add_seconds(2, exit_server, NULL);
328 static int __check_backend_status_for_exit(void)
331 for (i = 0; i < num_of_backends; i++) {
332 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++) {
347 if (ptr->queue_slot <= slot) {
351 slot = ptr->queue_slot;
356 for (i = 0; i < num_of_backends; i++) {
363 gboolean exit_server(void *data)
365 DBG("exit_server Start\n");
366 if (__check_backend_status_for_exit() &&
367 __check_queue_status_for_exit()) {
368 if (!getenv("PMS_STANDALONE")) {
369 g_main_loop_quit(mainloop);
376 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
380 if (buf == NULL || path == NULL)
382 fd = open(path, O_RDONLY);
385 ret = read(fd, buf, size - 1);
395 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
396 const char *cmdline, const char *apppath)
401 if (strcmp(cmdline, apppath) == 0) {
405 ERR("getpgid failed, errno(%d)", errno);
414 static int __check_csr(backend_info *ptr)
416 csr_cs_context_h context = NULL;
417 csr_cs_malware_h detected = NULL;
420 ret = csr_cs_context_create(&context);
\r
421 if (ret != CSR_ERROR_NONE) {
422 ERR("Failed to create csr context");
427 ret = csr_cs_scan_file(context, ptr->pkgid, &detected);
428 if (ret != CSR_ERROR_NONE) {
429 ERR("Failed to scan file[%d]", ret);
433 csr_cs_context_destroy(context);
434 if (detected != NULL) {
435 ERR("CSR Denied[%s] Installation", ptr->pkgid);
443 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
446 struct dirent dentry, *result;
449 char buf[1024] = {'\0'};
452 dp = opendir("/proc");
456 for (ret = readdir_r(dp, &dentry, &result);
457 ret == 0 && result != NULL;
458 ret = readdir_r(dp, &dentry, &result)) {
459 if (!isdigit(dentry.d_name[0]))
462 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
463 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
467 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
476 ERR("getpgid failed, errno(%d)", errno);
479 if (killpg(pgid, SIGKILL) < 0) {
481 ERR("killpg failed, errno(%d)", errno);
492 static void __make_pid_info_file(char *req_key, int pid, uid_t uid)
497 char buf[MAX_PKG_TYPE_LEN] = {0};
498 char info_file[PATH_MAX] = {'\0'};
500 struct passwd *pwd_result;
505 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
506 if (ret != 0 || pwd_result == NULL) {
507 ERR("get uid failed(%d) for user(%d)", ret, uid);
510 DBG("uid(%d), gid(%d)", uid, pwd.pw_gid);
512 snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
514 DBG("info_path(%s)", info_file);
515 file = fopen(info_file, "w");
517 ERR("Couldn't open the file(%s)", info_file);
521 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
522 fwrite(buf, 1, strlen(buf), file);
526 if (fchmod(fd, 0777) < 0)
527 ERR("chmod failed, errno(%d)", errno);
528 if (fchown(fd, uid, pwd.pw_gid) < 0)
529 ERR("chown failed, errno(%d)", errno);
534 static int __kill_app(char *appid, uid_t uid)
536 pkgmgrinfo_appinfo_h appinfo;
537 int ret = PMINFO_R_ERROR;
540 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
541 if (ret != PMINFO_R_OK)
542 return PMINFO_R_ERROR;
544 ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
545 if (ret != PMINFO_R_OK) {
546 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
547 return PMINFO_R_ERROR;
550 ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
551 if (ret != PMINFO_R_OK)
552 DBG("failed to kill app[%s], exec[%s]", appid, exec);
554 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
558 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
564 pkgcmd_data *pdata = (pkgcmd_data *)user_data;
566 if (handle == NULL) {
567 perror("appinfo handle is NULL\n");
570 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
572 perror("Failed to get app exec path\n");
575 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
577 perror("Failed to get pkgid\n");
581 if (strcmp(pdata->cmd, "kill") == 0)
582 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
583 else if (strcmp(pdata->cmd, "check") == 0)
584 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
586 __make_pid_info_file(pkgid, pid, pdata->uid);
591 void free_user_context(user_ctx* ctx)
598 /* env variable ends by NULL element */
608 int set_environement(user_ctx *ctx)
619 n = getgroups(0, NULL);
621 ERR("Failed to get the number of supplementary group IDs");
625 groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
626 if (groups == NULL) {
627 ERR("out of memory");
631 n = getgroups(n, groups);
633 ERR("Failed to get list of supplementary group IDs");
638 groups[n++] = EXT_STORAGE_GROUP;
639 groups[n++] = EXT_STORAGE_APPDATA_GROUP;
640 groups[n++] = MEDIA_STORAGE_GROUP;
642 if (setgroups(n, groups) < 0) {
643 ERR("setgroups failed: %d", errno);
650 /* env variable ends by NULL element */
652 if (putenv(env[i]) != 0)
659 user_ctx *get_user_context(uid_t uid)
661 /* we can use getpwnam because this is used only after a
662 * fork and just before an execv
663 * No concurrencial call can corrupt the data
664 * returned by getpwuid
666 user_ctx *context_res;
668 char buf[1024] = {0, };
669 struct passwd pwd, *result;
674 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
675 if (ret != 0 || result == NULL)
679 context_res = (user_ctx *)malloc(sizeof(user_ctx));
684 env = (char **)malloc(3 * sizeof(char *));
689 /* Build environment context */
690 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
691 env[0] = (char *)malloc((len + 1) * sizeof(char));
692 if (env[0] == NULL) {
696 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
697 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
698 env[1] = (char *)malloc((len + 1) * sizeof(char));
699 if (env[1] == NULL) {
703 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
711 /* env variable ends by NULL element */
712 while (env && env[i]) {
719 context_res->env = env;
720 context_res->uid = uid;
721 context_res->gid = pwd.pw_gid;
726 static char **__generate_argv(const char *args)
728 /* Create args vector
729 * req_id + pkgid + args
731 * vector size = # of args +
732 *(req_id + pkgid + NULL termination = 3)
733 * Last value must be NULL for execv.
741 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
742 if (FALSE == ret_parse) {
743 DBG("Failed to split args: %s", args);
744 DBG("messsage: %s", gerr->message);
749 for (i = 0; i < argcp; i++)
750 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
755 void __set_environment(gpointer user_data)
757 user_ctx *ctx = (user_ctx *)user_data;
759 if (set_environement(ctx))
760 DBG("Failed to set env for the user : %d", ctx->uid);
763 static int __fork_and_exec_with_args(char **argv, uid_t uid)
765 user_ctx* user_context;
766 GError *error = NULL;
770 user_context = get_user_context(uid);
772 DBG("Failed to getenv");
776 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
777 __set_environment, (gpointer)user_context, &pid,
780 ERR("Failed to excute backend: %s", error->message);
784 free_user_context(user_context);
789 static int __change_item_info(pm_dbus_msg *item, uid_t uid, bool *is_global)
793 pkgmgrinfo_appinfo_h handle = NULL;
795 switch (item->req_type) {
796 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
797 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
798 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
799 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
800 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
802 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
803 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
804 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
807 return PMINFO_R_ERROR;
810 if (ret != PMINFO_R_OK)
811 return PMINFO_R_ERROR;
813 ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
814 if (ret != PMINFO_R_OK)
817 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
818 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
820 ret = PMINFO_R_ERROR;
822 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
823 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
825 ret = PMINFO_R_ERROR;
829 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
830 if (ret != PMINFO_R_OK)
833 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
834 memset((item->pkgid), 0, MAX_PKG_NAME_LEN);
835 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
838 pkgmgrinfo_appinfo_destroy_appinfo(handle);
843 static int __process_install(pm_dbus_msg *item)
847 char args[MAX_PKG_ARGS_LEN] = {'\0', };
850 backend_cmd = _get_backend_cmd(item->pkg_type);
851 if (backend_cmd == NULL)
854 snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
855 item->req_id, item->pkgid, (int)item->uid, item->args);
857 argv = __generate_argv(args);
859 pid = __fork_and_exec_with_args(argv, APPFW_UID);
866 static int __process_mount_install(pm_dbus_msg *item)
870 char args[MAX_PKG_ARGS_LEN] = {'\0', };
873 backend_cmd = _get_backend_cmd(item->pkg_type);
874 if (backend_cmd == NULL)
877 snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
878 item->req_id, item->pkgid, (int)item->uid, item->args);
880 argv = __generate_argv(args);
882 pid = __fork_and_exec_with_args(argv, APPFW_UID);
889 static int __process_reinstall(pm_dbus_msg *item)
893 char args[MAX_PKG_ARGS_LEN];
896 backend_cmd = _get_backend_cmd(item->pkg_type);
897 if (backend_cmd == NULL)
900 snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
901 item->req_id, item->pkgid, (int)item->uid);
902 argv = __generate_argv(args);
904 pid = __fork_and_exec_with_args(argv, APPFW_UID);
912 static int __process_uninstall(pm_dbus_msg *item)
916 char args[MAX_PKG_ARGS_LEN];
919 backend_cmd = _get_backend_cmd(item->pkg_type);
920 if (backend_cmd == NULL)
923 snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
924 item->req_id, item->pkgid, (int)item->uid);
925 argv = __generate_argv(args);
927 pid = __fork_and_exec_with_args(argv, APPFW_UID);
935 static int __process_move(pm_dbus_msg *item)
939 char args[MAX_PKG_ARGS_LEN];
942 backend_cmd = _get_backend_cmd(item->pkg_type);
943 if (backend_cmd == NULL)
946 snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
947 item->req_id, item->pkgid, (int)item->uid, item->args);
948 argv = __generate_argv(args);
950 pid = __fork_and_exec_with_args(argv, APPFW_UID);
958 static int __process_enable_pkg(pm_dbus_msg *item)
962 char args[MAX_PKG_ARGS_LEN];
965 backend_cmd = _get_backend_cmd(item->pkg_type);
966 if (backend_cmd == NULL)
969 snprintf(args, sizeof(args), "%s -k %s -u %d -A %s", backend_cmd,
970 item->req_id, (int)item->uid, item->pkgid);
971 argv = __generate_argv(args);
973 pid = __fork_and_exec_with_args(argv, APPFW_UID);
981 static int __process_disable_pkg(pm_dbus_msg *item)
985 char args[MAX_PKG_ARGS_LEN];
988 backend_cmd = _get_backend_cmd(item->pkg_type);
989 if (backend_cmd == NULL)
992 snprintf(args, sizeof(args), "%s -k %s -u %d -D %s", backend_cmd,
993 item->req_id, (int)item->uid, item->pkgid);
994 argv = __generate_argv(args);
996 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1004 static int __process_enable_app(pm_dbus_msg *item)
1007 bool is_global = false;
1009 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1010 PKGMGR_INSTALLER_START_KEY_STR,
1011 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, item->req_type);
1013 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1014 ret = __change_item_info(item, item->uid, &is_global);
1015 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1016 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1017 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, 0);
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,
1036 static int __process_disable_app(pm_dbus_msg *item)
1039 bool is_global = false;
1041 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1042 PKGMGR_INSTALLER_START_KEY_STR,
1043 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, item->req_type);
1045 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1046 ret = __change_item_info(item, item->uid, &is_global);
1047 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1048 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1049 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1054 ret = __kill_app(item->appid, item->uid);
1055 if (ret != PMINFO_R_OK) {
1056 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1057 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1061 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
1062 if (ret != PMINFO_R_OK)
1063 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1064 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1067 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1068 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1074 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
1077 bool is_global = true;
1079 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1080 PKGMGR_INSTALLER_START_KEY_STR,
1081 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID, item->req_type);
1083 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1084 ret = __change_item_info(item, item->uid, &is_global);
1085 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1086 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1087 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1092 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
1093 if (ret != PMINFO_R_OK)
1094 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1095 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1098 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1099 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1105 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
1108 bool is_global = true;
1110 __send_app_signal(item->uid, item->req_id,
1111 item->pkgid, item->pkgid,
1112 PKGMGR_INSTALLER_START_KEY_STR,
1113 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID, item->req_type);
1115 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1116 ret = __change_item_info(item, GLOBAL_USER, &is_global);
1117 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1118 __send_app_signal(item->uid, item->req_id, item->pkgid, item->pkgid,
1119 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1124 ret = __kill_app(item->appid, item->uid);
1125 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid,
1128 if (ret != PMINFO_R_OK)
1129 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1130 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR,
1133 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1134 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR,
1140 static int __process_getsize(pm_dbus_msg *item)
1142 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1144 char args[MAX_PKG_ARGS_LEN];
1147 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1148 item->args, item->req_id);
1149 argv = __generate_argv(args);
1150 pid = __fork_and_exec_with_args(argv, item->uid);
1157 static int __process_cleardata(pm_dbus_msg *item)
1161 char args[MAX_PKG_ARGS_LEN];
1164 backend_cmd = _get_backend_cmd(item->pkg_type);
1165 if (backend_cmd == NULL)
1168 /* TODO: set movetype */
1169 snprintf(args, sizeof(args), "%s -k %s -c %s -u %d", backend_cmd,
1170 item->req_id, item->pkgid, (int)item->uid);
1171 argv = __generate_argv(args);
1173 pid = __fork_and_exec_with_args(argv, APPFW_UID);
1181 static int __process_clearcache(pm_dbus_msg *item)
1183 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1185 char args[MAX_PKG_ARGS_LEN];
1188 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1189 argv = __generate_argv(args);
1190 pid = __fork_and_exec_with_args(argv, item->uid);
1197 static int __process_kill(pm_dbus_msg *item)
1200 pkgmgrinfo_pkginfo_h handle;
1201 pkgcmd_data *pdata = NULL;
1203 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1206 ERR("Failed to get handle");
1210 pdata = calloc(1, sizeof(pkgcmd_data));
1211 if (pdata == NULL) {
1212 ERR("memory alloc failed");
1215 pdata->cmd = strdup("kill");
1216 if (pdata->cmd == NULL) {
1217 ERR("out of memory");
1222 pdata->uid = item->uid;
1223 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1224 __pkgcmd_app_cb, pdata, item->uid);
1228 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1230 ERR("pkgmgrinfo_appinfo_get_list() failed");
1237 static int __process_check(pm_dbus_msg *item)
1240 pkgmgrinfo_pkginfo_h handle;
1241 pkgcmd_data *pdata = NULL;
1243 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1246 ERR("Failed to get handle");
1250 pdata = calloc(1, sizeof(pkgcmd_data));
1251 if (pdata == NULL) {
1252 ERR("memory alloc failed");
1255 pdata->cmd = strdup("check");
1256 if (pdata->cmd == NULL) {
1257 ERR("out of memory");
1262 pdata->uid = item->uid;
1263 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1264 __pkgcmd_app_cb, pdata, item->uid);
1268 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1270 ERR("pkgmgrinfo_appinfo_get_list() failed");
1277 static int __process_generate_license_request(pm_dbus_msg *item)
1281 char req_data[MAX_PKG_ARGS_LEN];
1282 unsigned int req_data_len;
1283 char license_url[MAX_PKG_ARGS_LEN];
1284 unsigned int license_url_len;
1286 resp_data = item->args;
1287 req_data_len = sizeof(req_data);
1288 license_url_len = sizeof(license_url);
1290 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1291 req_data, &req_data_len, license_url, &license_url_len);
1292 if (ret != TADC_SUCCESS) {
1293 ERR("drm_tizen_generate_license_request failed: %d", ret);
1294 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1295 PKGMGR_R_ESYSTEM, "", ""));
1299 __return_value_to_caller(item->req_id,
1300 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1306 static int __process_register_license(pm_dbus_msg *item)
1311 resp_data = item->args;
1313 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1314 if (ret != TADC_SUCCESS) {
1315 ERR("drm_tizen_register_license failed: %d", ret);
1316 __return_value_to_caller(item->req_id,
1317 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1321 __return_value_to_caller(item->req_id,
1322 g_variant_new("(i)", PKGMGR_R_OK));
1327 static int __process_decrypt_package(pm_dbus_msg *item)
1330 char *drm_file_path;
1331 char *decrypted_file_path;
1333 drm_file_path = item->pkgid;
1334 decrypted_file_path = item->args;
1336 /* TODO: check ownership of decrypted file */
1337 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1338 decrypted_file_path, strlen(decrypted_file_path));
1339 if (ret != TADC_SUCCESS) {
1340 ERR("drm_tizen_register_license failed: %d", ret);
1341 __return_value_to_caller(item->req_id,
1342 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1346 __return_value_to_caller(item->req_id,
1347 g_variant_new("(i)", PKGMGR_R_OK));
1352 static int __process_update_app_splash_screen(pm_dbus_msg *item, int flag)
1355 bool is_global = false;
1358 ret = __change_item_info(item, item->uid, &is_global);
1359 if (ret != PMINFO_R_OK || strlen(item->appid) == 0)
1362 val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1363 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1364 __send_app_signal(item->uid, item->req_id, item->pkgid, item->appid,
1365 PKGMGR_INSTALLER_START_KEY_STR, val, item->req_type);
1368 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
1369 item->appid, item->uid, flag);
1371 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1372 item->appid, item->uid, flag);
1373 if (ret != PMINFO_R_OK)
1374 __send_app_signal(item->uid, item->req_id, item->pkgid,
1375 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1376 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1379 __send_app_signal(item->uid, item->req_id, item->pkgid,
1380 item->appid, PKGMGR_INSTALLER_END_KEY_STR,
1381 PKGMGR_INSTALLER_OK_EVENT_STR,
1387 static int __process_set_restriction_mode(pm_dbus_msg *item)
1392 mode = atoi(item->args);
1393 ret = _restriction_mode_set(item->uid, item->pkgid, mode);
1395 __return_value_to_caller(item->req_id,
1396 g_variant_new("(i)", ret));
1401 static int __process_unset_restriction_mode(pm_dbus_msg *item)
1406 mode = atoi(item->args);
1407 ret = _restriction_mode_unset(item->uid, item->pkgid, mode);
1409 __return_value_to_caller(item->req_id,
1410 g_variant_new("(i)", ret));
1415 static int __process_get_restriction_mode(pm_dbus_msg *item)
1420 ret = _restriction_mode_get(item->uid, item->pkgid, &mode);
1422 __return_value_to_caller(item->req_id,
1423 g_variant_new("(ii)", mode, ret));
1428 gboolean queue_job(void *data)
1430 pm_dbus_msg *item = NULL;
1435 /* Pop a job from queue */
1436 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1437 if (__is_backend_busy(x))
1440 item = _pm_queue_pop(x);
1441 if (item && item->req_type != -1)
1446 /* all backend messages queue are empty or busy */
1447 if (x == num_of_backends)
1450 /*save pkg type and pkg name for future*/
1451 strncpy(ptr->req_id, item->req_id, MAX_REQ_ID_LEN - 1);
1452 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN - 1);
1453 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN - 1);
1454 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN - 1);
1455 memset((item->appid), 0, MAX_PKG_NAME_LEN);
1456 ptr->uid = item->uid;
1457 ptr->req_type = item->req_type;
1458 DBG("handle request type [%d]", item->req_type);
1460 if (item->req_type == PKGMGR_REQUEST_TYPE_INSTALL ||
1461 item->req_type == PKGMGR_REQUEST_TYPE_MOUNT_INSTALL ||
1462 item->req_type == PKGMGR_REQUEST_TYPE_REINSTALL) {
1463 ret = __check_csr(ptr);
1466 __send_fail_signal(ptr);
1471 switch (item->req_type) {
1472 case PKGMGR_REQUEST_TYPE_INSTALL:
1473 __set_backend_busy(x);
1474 ret = __process_install(item);
1476 case PKGMGR_REQUEST_TYPE_MOUNT_INSTALL:
1477 __set_backend_busy(x);
1478 ret = __process_mount_install(item);
1480 case PKGMGR_REQUEST_TYPE_REINSTALL:
1481 __set_backend_busy(x);
1482 ret = __process_reinstall(item);
1484 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1485 __set_backend_busy(x);
1486 ret = __process_uninstall(item);
1488 case PKGMGR_REQUEST_TYPE_MOVE:
1489 __set_backend_busy(x);
1490 ret = __process_move(item);
1492 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1493 ret = __process_enable_pkg(item);
1495 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1496 ret = __process_disable_pkg(item);
1498 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1499 ret = __process_enable_app(item);
1501 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1502 ret = __process_disable_app(item);
1504 case PKGMGR_REQUEST_TYPE_GETSIZE:
1505 __set_backend_busy(x);
1506 ret = __process_getsize(item);
1508 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1509 __set_backend_busy(x);
1510 ret = __process_cleardata(item);
1512 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1513 __set_backend_busy(x);
1514 ret = __process_clearcache(item);
1516 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1517 ret = __process_enable_global_app_for_uid(item);
1519 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1520 ret = __process_disable_global_app_for_uid(item);
1522 case PKGMGR_REQUEST_TYPE_KILL:
1523 ret = __process_kill(item);
1525 case PKGMGR_REQUEST_TYPE_CHECK:
1526 ret = __process_check(item);
1528 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1529 ret = __process_generate_license_request(item);
1531 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1532 ret = __process_register_license(item);
1534 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1535 ret = __process_decrypt_package(item);
1537 case PKGMGR_REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1538 ret = __process_update_app_splash_screen(item, 1);
1540 case PKGMGR_REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1541 ret = __process_update_app_splash_screen(item, 0);
1543 case PKGMGR_REQUEST_TYPE_SET_RESTRICTION_MODE:
1544 ret = __process_set_restriction_mode(item);
1546 case PKGMGR_REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1547 ret = __process_unset_restriction_mode(item);
1549 case PKGMGR_REQUEST_TYPE_GET_RESTRICTION_MODE:
1550 ret = __process_get_restriction_mode(item);
1564 #define IS_WHITESPACE(CHAR) \
1565 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1567 void _app_str_trim(char *input)
1569 char *trim_str = input;
1574 while (*input != 0) {
1575 if (!IS_WHITESPACE(*input)) {
1586 char *_get_backend_cmd(char *type)
1589 char buffer[1024] = { 0 };
1590 char *command = NULL;
1593 fp = fopen(PKG_CONF_PATH, "r");
1598 while (fgets(buffer, 1024, fp) != NULL) {
1599 if (buffer[0] == '#')
1602 _app_str_trim(buffer);
1604 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1605 DBG("buffer [%s]", buffer);
1606 path = path + strlen(PKG_BACKEND);
1607 DBG("path [%s]", path);
1610 (char *)malloc(sizeof(char) * strlen(path) +
1612 if (command == NULL) {
1617 size = strlen(path) + strlen(type) + 1;
1618 snprintf(command, size, "%s%s", path, type);
1619 command[strlen(path) + strlen(type)] = '\0';
1620 DBG("command [%s]", command);
1628 memset(buffer, 0x00, 1024);
1634 return NULL; /* cannot find proper command */
1637 int main(int argc, char *argv[])
1641 DBG("server start");
1643 r = _pm_queue_init();
1645 DBG("Queue Initialization Failed\n");
1649 r = __init_backend_info();
1651 DBG("backend info init failed");
1655 r = __init_request_handler();
1657 ERR("dbus init failed");
1661 if (__register_signal_handler()) {
1662 ERR("failed to register signal handler");
1666 #if !GLIB_CHECK_VERSION(2, 35, 0)
1669 mainloop = g_main_loop_new(NULL, FALSE);
1671 ERR("g_main_loop_new failed");
1675 DBG("Main loop is created.");
1677 g_main_loop_run(mainloop);
1679 DBG("Quit main loop.");
1680 __fini_request_handler();
1681 __fini_backend_info();
1684 DBG("package manager server terminated.");