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>
40 #include <pkgmgr-info.h>
41 #include <pkgmgr/pkgmgr_parser_db.h>
42 #include <tzplatform_config.h>
43 #include <drm-tizen-apps.h>
45 #include "pkgmgr_installer.h"
46 #include "pkgmgr-server.h"
48 #include "comm_config.h"
49 #include "package-manager.h"
52 #define NO_MATCHING_FILE 11
55 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
65 8 bit value to represent maximum 8 backends.
66 Each bit position corresponds to a queue slot which
67 is dynamically determined.
69 char backend_busy = 0;
70 extern int num_of_backends;
72 struct signal_info_t {
77 static int pipe_sig[2];
78 static GIOChannel *pipe_io;
79 static guint pipe_wid;
82 extern queue_info_map *start;
85 GMainLoop *mainloop = NULL;
90 OPERATION_INSTALL = 0,
97 static int __check_backend_status_for_exit(void);
98 static int __check_queue_status_for_exit(void);
99 static int __is_backend_busy(int position);
100 static void __set_backend_busy(int position);
101 static void __set_backend_free(int position);
102 static void sighandler(int signo);
104 gboolean exit_server(void *data);
106 /* To check whether a particular backend is free/busy*/
107 static int __is_backend_busy(int position)
109 return backend_busy & 1<<position;
111 /*To set a particular backend as busy*/
112 static void __set_backend_busy(int position)
114 backend_busy = backend_busy | 1<<position;
116 /*To set a particular backend as free */
117 static void __set_backend_free(int position)
119 backend_busy = backend_busy & ~(1<<position);
122 static int __is_global(uid_t uid)
124 return (uid == OWNER_ROOT || uid == GLOBAL_USER) ? 1 : 0;
127 static const char *__get_recovery_file_path(uid_t uid)
131 if (!__is_global(uid))
132 tzplatform_set_user(uid);
134 path = tzplatform_getenv(__is_global(uid)
135 ? TZ_SYS_RW_PACKAGES : TZ_USER_PACKAGES);
137 tzplatform_reset_user();
142 static void __set_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
144 char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
145 char buffer[MAX_PKG_NAME_LEN] = { 0 };
146 char *pkgid_tmp = NULL;
147 FILE *rev_file = NULL;
150 DBG("pkgid is null\n");
154 /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
155 if (strstr(pkgid, "/")) {
156 pkgid_tmp = strrchr(pkgid, '/') + 1;
157 if (pkgid_tmp == NULL) {
158 DBG("pkgid_tmp[%s] is null\n", pkgid);
161 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
163 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
166 rev_file = fopen(recovery_file, "w");
167 if (rev_file== NULL) {
168 DBG("rev_file[%s] is null\n", recovery_file);
172 snprintf(buffer, MAX_PKG_NAME_LEN, "pkgid : %s\n", pkgid);
173 fwrite(buffer, sizeof(char), strlen(buffer), rev_file);
178 static void __unset_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
181 char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
182 char *pkgid_tmp = NULL;
185 DBG("pkgid is null\n");
189 /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
190 if (strstr(pkgid, "/")) {
191 pkgid_tmp = strrchr(pkgid, '/') + 1;
192 if (pkgid_tmp == NULL) {
193 DBG("pkgid_tmp[%s] is null\n", pkgid);
196 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
198 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
201 ret = remove(recovery_file);
203 DBG("remove recovery_file[%s] fail\n", recovery_file);
206 static void __send_app_signal(uid_t uid, const char *req_id,
207 const char *pkg_type, const char *pkgid, const char *appid,
208 const char *key, const char *val)
210 pkgmgr_installer *pi;
212 pi = pkgmgr_installer_new();
214 DBG("Failure in creating the pkgmgr_installer object");
218 if (pkgmgr_installer_set_uid(pi, uid))
220 if (pkgmgr_installer_set_request_type(pi,PKGMGR_REQ_ENABLE_DISABLE_APP))
222 if (pkgmgr_installer_set_session_id(pi, req_id))
224 pkgmgr_installer_send_app_signal(pi, pkg_type, pkgid, appid, key, val);
227 pkgmgr_installer_free(pi);
232 static void send_fail_signal(char *pname, char *ptype, char *args)
234 DBG("send_fail_signal start\n");
239 pkgmgr_installer *pi;
240 pi = pkgmgr_installer_new();
242 DBG("Failure in creating the pkgmgr_installer object");
245 ret_parse = g_shell_parse_argv(args,
246 &argcp, &argvp, &gerr);
247 if (FALSE == ret_parse) {
248 DBG("Failed to split args: %s", args);
249 DBG("messsage: %s", gerr->message);
250 pkgmgr_installer_free(pi);
254 pkgmgr_installer_receive_request(pi, argcp, argvp);
255 pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
256 pkgmgr_installer_free(pi);
260 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
266 struct signal_info_t info;
267 backend_info *ptr = begin;
269 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
270 if (s != G_IO_STATUS_NORMAL) {
271 ERR("Signal pipe read failed: %s", err->message);
276 for (x = 0; x < num_of_backends; x++, ptr++) {
277 if (ptr && ptr->pid == info.pid)
281 if (x == num_of_backends) {
282 ERR("Unknown child exit");
286 __set_backend_free(x);
287 __unset_recovery_mode(ptr->uid, ptr->pkgid, ptr->pkgtype);
288 if (WIFSIGNALED(info.status) || WEXITSTATUS(info.status)) {
289 send_fail_signal(ptr->pkgid, ptr->pkgtype, ptr->args);
290 DBG("backend[%s] exit with error", ptr->pkgtype);
292 DBG("backend[%s] exit", ptr->pkgtype);
295 g_idle_add(queue_job, NULL);
300 static int __init_backend_info(void)
304 /*Allocate memory for holding pid, pkgtype and pkgid*/
305 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
307 DBG("Malloc Failed\n");
312 if (pipe(pipe_sig)) {
313 ERR("create pipe failed");
317 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
318 g_io_channel_set_encoding(pipe_io, NULL, NULL);
319 g_io_channel_set_buffered(pipe_io, FALSE);
320 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
325 static void __fini_backend_info(void)
327 g_source_remove(pipe_wid);
328 g_io_channel_unref(pipe_io);
332 /*Free backend info */
336 static void sighandler(int signo)
338 struct signal_info_t info;
339 char buf[1024] = {0, };
341 info.pid = waitpid(-1, &info.status, WNOHANG);
342 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
343 ERR("failed to write result: %s", strerror_r(errno, buf, sizeof(buf)));
346 static int __register_signal_handler(void)
348 static int sig_reg = 0;
349 struct sigaction act;
354 act.sa_handler = sighandler;
355 sigemptyset(&act.sa_mask);
356 act.sa_flags = SA_NOCLDSTOP;
357 if (sigaction(SIGCHLD, &act, NULL) < 0) {
358 ERR("signal: SIGCHLD failed\n");
362 g_timeout_add_seconds(2, exit_server, NULL);
368 static int __check_backend_status_for_exit(void)
371 for(i = 0; i < num_of_backends; i++)
373 if (!__is_backend_busy(i))
381 static int __check_queue_status_for_exit(void)
383 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
384 queue_info_map *ptr = NULL;
389 for(i = 0; i < entries; i++)
391 if (ptr->queue_slot <= slot) {
397 slot = ptr->queue_slot;
402 for(i = 0; i < num_of_backends; i++)
412 gboolean exit_server(void *data)
414 DBG("exit_server Start\n");
415 if (__check_backend_status_for_exit() &&
416 __check_queue_status_for_exit()) {
417 if (!getenv("PMS_STANDALONE")) {
418 g_main_loop_quit(mainloop);
425 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
429 if (buf == NULL || path == NULL)
431 fd = open(path, O_RDONLY);
434 ret = read(fd, buf, size - 1);
444 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
445 const char *cmdline, const char *apppath)
449 if (strcmp(cmdline, apppath) == 0) {
451 if (pid != getpgid(pid))
457 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
460 struct dirent dentry, *result;
463 char buf[1024] = {'\0'};
466 dp = opendir("/proc");
471 for (ret = readdir_r(dp, &dentry, &result);
472 ret == 0 && result != NULL;
473 ret = readdir_r(dp, &dentry, &result)) {
474 if (!isdigit(dentry.d_name[0]))
477 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry.d_name);
478 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
482 pid = __pkgcmd_find_pid_by_cmdline(dentry.d_name, buf, apppath);
493 if (killpg(pgid, SIGKILL) < 0) {
505 static void __make_pid_info_file(char *req_key, int pid)
509 char buf[MAX_PKG_TYPE_LEN] = {0};
510 char info_file[PATH_MAX] = {'\0'};
515 snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key);
517 DBG("info_path(%s)", info_file);
518 file = fopen(info_file, "w");
520 ERR("Couldn't open the file(%s)", info_file);
524 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
525 fwrite(buf, 1, strlen(buf), file);
533 static int __kill_app(char *appid, uid_t uid)
535 pkgmgrinfo_appinfo_h appinfo;
536 int ret = PMINFO_R_ERROR;
539 ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &appinfo);
540 if (ret != PMINFO_R_OK)
541 return PMINFO_R_ERROR;
543 ret = pkgmgrinfo_appinfo_get_exec(appinfo, &exec);
544 if (ret != PMINFO_R_OK) {
545 pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
546 return PMINFO_R_ERROR;
549 ret = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
550 if (ret != PMINFO_R_OK) {
551 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)
565 if (handle == NULL) {
566 perror("appinfo handle is NULL\n");
569 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
571 perror("Failed to get app exec path\n");
574 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
576 perror("Failed to get pkgid\n");
580 if (strcmp(user_data, "kill") == 0)
581 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
582 else if(strcmp(user_data, "check") == 0)
583 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
585 __make_pid_info_file(pkgid, pid);
590 void free_user_context(user_ctx* ctx)
597 //env variable ends by NULL element
607 int set_environement(user_ctx *ctx)
614 if (setgid(ctx->gid)) {
615 ERR("setgid failed: %d", errno);
618 if (setuid(ctx->uid)) {
619 ERR("setuid failed: %d", errno);
623 //env variable ends by NULL element
625 if (putenv(env[i]) != 0)
632 user_ctx *get_user_context(uid_t uid)
634 /* we can use getpwnam because this is used only after a
635 * fork and just before an execv
636 * No concurrencial call can corrupt the data
637 * returned by getpwuid
639 user_ctx *context_res;
641 char buf[1024] = {0, };
642 struct passwd pwd, *result;
647 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
648 if (ret != 0 || result == NULL)
652 context_res = (user_ctx *)malloc(sizeof(user_ctx));
657 env = (char **)malloc(3 * sizeof(char *));
662 // Build environment context
663 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
664 env[0] = (char *)malloc((len + 1) * sizeof(char));
669 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
670 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
671 env[1] = (char *)malloc((len + 1) * sizeof(char));
676 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
684 //env variable ends by NULL element
685 while (env && env[i]) {
692 context_res->env = env;
693 context_res->uid = uid;
694 context_res->gid = pwd.pw_gid;
699 static char **__generate_argv(const char *args)
701 /* Create args vector
702 * req_id + pkgid + args
704 * vector size = # of args +
705 *(req_id + pkgid + NULL termination = 3)
706 * Last value must be NULL for execv.
714 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
715 if (FALSE == ret_parse) {
716 DBG("Failed to split args: %s", args);
717 DBG("messsage: %s", gerr->message);
722 for (i = 0; i < argcp; i++)
723 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
728 void __set_environment(gpointer user_data)
730 user_ctx *ctx = (user_ctx *)user_data;
732 if (set_environement(ctx))
733 DBG("Failed to set env for the user : %d", ctx->uid);
736 static int __fork_and_exec_with_args(char **argv, uid_t uid)
738 user_ctx* user_context;
739 GError *error = NULL;
743 user_context = get_user_context(uid);
745 DBG("Failed to getenv for the user : %d", uid);
749 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
750 __set_environment, (gpointer)user_context, &pid,
753 ERR("Failed to excute backend: %s", error->message);
757 free_user_context(user_context);
762 static int __change_item_info(pm_dbus_msg *item, uid_t uid)
766 bool is_global = false;
767 pkgmgrinfo_appinfo_h handle = NULL;
769 switch (item->req_type) {
770 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
771 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
772 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
775 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
776 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
777 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
781 return PMINFO_R_ERROR;
784 if (ret != PMINFO_R_OK)
785 return PMINFO_R_ERROR;
787 ret = pkgmgrinfo_appinfo_is_global(handle, &is_global);
788 if (ret != PMINFO_R_OK)
791 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
792 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
794 ret = PMINFO_R_ERROR;
796 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
797 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
799 ret = PMINFO_R_ERROR;
803 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
804 if (ret != PMINFO_R_OK)
807 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
808 memset((item->pkgid),0,MAX_PKG_NAME_LEN);
809 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
812 pkgmgrinfo_appinfo_destroy_appinfo(handle);
817 static int __process_install(pm_dbus_msg *item)
821 char args[MAX_PKG_ARGS_LEN] = {'\0', };
824 backend_cmd = _get_backend_cmd(item->pkg_type);
825 if (backend_cmd == NULL)
828 snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd,
829 item->req_id, item->pkgid, item->args);
831 argv = __generate_argv(args);
833 pid = __fork_and_exec_with_args(argv, item->uid);
840 static int __process_reinstall(pm_dbus_msg *item)
844 char args[MAX_PKG_ARGS_LEN];
847 backend_cmd = _get_backend_cmd(item->pkg_type);
848 if (backend_cmd == NULL)
851 snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
852 item->req_id, item->pkgid);
853 argv = __generate_argv(args);
855 pid = __fork_and_exec_with_args(argv, item->uid);
863 static int __process_uninstall(pm_dbus_msg *item)
867 char args[MAX_PKG_ARGS_LEN];
870 backend_cmd = _get_backend_cmd(item->pkg_type);
871 if (backend_cmd == NULL)
874 snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
875 item->req_id, item->pkgid);
876 argv = __generate_argv(args);
878 pid = __fork_and_exec_with_args(argv, item->uid);
886 static int __process_move(pm_dbus_msg *item)
890 char args[MAX_PKG_ARGS_LEN];
893 backend_cmd = _get_backend_cmd(item->pkg_type);
894 if (backend_cmd == NULL)
897 /* TODO: set movetype */
898 snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
899 item->req_id, item->pkgid, item->args);
900 argv = __generate_argv(args);
902 pid = __fork_and_exec_with_args(argv, item->uid);
910 static int __process_enable_pkg(pm_dbus_msg *item)
916 static int __process_disable_pkg(pm_dbus_msg *item)
922 static int __process_enable_app(pm_dbus_msg *item)
926 __send_app_signal(item->uid, item->req_id, item->pkg_type,
927 item->pkgid, item->pkgid,
928 PKGMGR_INSTALLER_START_KEY_STR,
929 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR);
931 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
932 ret = __change_item_info(item, item->uid);
933 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
934 __send_app_signal(item->uid, item->req_id, item->pkg_type,
935 item->pkgid, item->pkgid,
936 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
940 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
941 if (ret != PMINFO_R_OK)
942 __send_app_signal(item->uid, item->req_id, item->pkg_type,
943 item->pkgid, item->appid,
944 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
946 __send_app_signal(item->uid, item->req_id, item->pkg_type,
947 item->pkgid, item->appid,
948 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
953 static int __process_disable_app(pm_dbus_msg *item)
957 __send_app_signal(item->uid, item->req_id, item->pkg_type,
958 item->pkgid, item->pkgid,
959 PKGMGR_INSTALLER_START_KEY_STR,
960 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR);
962 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
963 ret = __change_item_info(item, item->uid);
964 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
965 __send_app_signal(item->uid, item->req_id, item->pkg_type,
966 item->pkgid, item->pkgid,
967 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
971 ret = __kill_app(item->appid, item->uid);
972 if (ret != PMINFO_R_OK) {
973 __send_app_signal(item->uid, item->req_id, item->pkg_type,
974 item->pkgid, item->appid,
975 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
978 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
979 if (ret != PMINFO_R_OK)
980 __send_app_signal(item->uid, item->req_id, item->pkg_type,
981 item->pkgid, item->appid,
982 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
984 __send_app_signal(item->uid, item->req_id, item->pkg_type,
985 item->pkgid, item->appid,
986 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
991 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
995 __send_app_signal(item->uid, item->req_id, item->pkg_type,
996 item->pkgid, item->pkgid,
997 PKGMGR_INSTALLER_START_KEY_STR,
998 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID);
1000 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1001 ret = __change_item_info(item, item->uid);
1002 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1003 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1004 item->pkgid, item->pkgid,
1005 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1009 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
1010 if (ret != PMINFO_R_OK)
1011 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1012 item->pkgid, item->appid,
1013 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1015 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1016 item->pkgid, item->appid,
1017 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
1022 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
1026 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1027 item->pkgid, item->pkgid,
1028 PKGMGR_INSTALLER_START_KEY_STR,
1029 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID);
1031 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
1032 ret = __change_item_info(item, GLOBAL_USER);
1033 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
1034 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1035 item->pkgid, item->pkgid,
1036 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1040 ret = __kill_app(item->appid, item->uid);
1042 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 1);
1043 if (ret != PMINFO_R_OK)
1044 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1045 item->pkgid, item->appid,
1046 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1048 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1049 item->pkgid, item->appid,
1050 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
1055 static int __process_getsize(pm_dbus_msg *item)
1057 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1059 char args[MAX_PKG_ARGS_LEN];
1062 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1063 item->args, item->req_id);
1064 argv = __generate_argv(args);
1065 pid = __fork_and_exec_with_args(argv, item->uid);
1072 static int __process_cleardata(pm_dbus_msg *item)
1076 char args[MAX_PKG_ARGS_LEN];
1079 backend_cmd = _get_backend_cmd(item->pkg_type);
1080 if (backend_cmd == NULL)
1083 /* TODO: set movetype */
1084 snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
1085 item->req_id, item->pkgid);
1086 argv = __generate_argv(args);
1088 pid = __fork_and_exec_with_args(argv, item->uid);
1096 static int __process_clearcache(pm_dbus_msg *item)
1098 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1100 char args[MAX_PKG_ARGS_LEN];
1103 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1104 argv = __generate_argv(args);
1105 pid = __fork_and_exec_with_args(argv, item->uid);
1112 static int __process_kill(pm_dbus_msg *item)
1115 pkgmgrinfo_pkginfo_h handle;
1117 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1120 ERR("Failed to get handle");
1124 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1125 __pkgcmd_app_cb, "kill", item->uid);
1126 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1128 ERR("pkgmgrinfo_appinfo_get_list() failed");
1135 static int __process_check(pm_dbus_msg *item)
1138 pkgmgrinfo_pkginfo_h handle;
1140 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1143 ERR("Failed to get handle");
1147 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1148 __pkgcmd_app_cb, "check", item->uid);
1149 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1151 ERR("pkgmgrinfo_appinfo_get_list() failed");
1158 static int __process_generate_license_request(pm_dbus_msg *item)
1162 char req_data[MAX_PKG_ARGS_LEN];
1163 unsigned int req_data_len;
1164 char license_url[MAX_PKG_ARGS_LEN];
1165 unsigned int license_url_len;
1167 resp_data = item->args;
1168 req_data_len = sizeof(req_data);
1169 license_url_len = sizeof(license_url);
1171 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1172 req_data, &req_data_len, license_url, &license_url_len);
1173 if (ret != TADC_SUCCESS) {
1174 ERR("drm_tizen_generate_license_request failed: %d", ret);
1175 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1176 PKGMGR_R_ESYSTEM, "", ""));
1180 __return_value_to_caller(item->req_id,
1181 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1187 static int __process_register_license(pm_dbus_msg *item)
1192 resp_data = item->args;
1194 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1195 if (ret != TADC_SUCCESS) {
1196 ERR("drm_tizen_register_license failed: %d", ret);
1197 __return_value_to_caller(item->req_id,
1198 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1202 __return_value_to_caller(item->req_id,
1203 g_variant_new("(i)", PKGMGR_R_OK));
1208 static int __process_decrypt_package(pm_dbus_msg *item)
1211 char *drm_file_path;
1212 char *decrypted_file_path;
1214 drm_file_path = item->pkgid;
1215 decrypted_file_path = item->args;
1217 /* TODO: check ownership of decrypted file */
1218 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1219 decrypted_file_path, strlen(decrypted_file_path));
1220 if (ret != TADC_SUCCESS) {
1221 ERR("drm_tizen_register_license failed: %d", ret);
1222 __return_value_to_caller(item->req_id,
1223 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1227 __return_value_to_caller(item->req_id,
1228 g_variant_new("(i)", PKGMGR_R_OK));
1233 static int __process_add_blacklist(pm_dbus_msg *item)
1237 ret = __add_blacklist(item->uid, item->pkgid);
1239 __return_value_to_caller(item->req_id,
1240 g_variant_new("(i)", ret));
1245 static int __process_remove_blacklist(pm_dbus_msg *item)
1249 ret = __remove_blacklist(item->uid, item->pkgid);
1251 __return_value_to_caller(item->req_id,
1252 g_variant_new("(i)", ret));
1257 static int __process_check_blacklist(pm_dbus_msg *item)
1262 ret = __check_blacklist(item->uid, item->pkgid, &result);
1264 __return_value_to_caller(item->req_id,
1265 g_variant_new("(ii)", result, ret));
1270 gboolean queue_job(void *data)
1272 pm_dbus_msg *item = NULL;
1277 /* Pop a job from queue */
1278 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1279 if (__is_backend_busy(x))
1282 item = _pm_queue_pop(x);
1283 if (item && item->req_type != -1)
1288 /* all backend messages queue are empty or busy */
1289 if (x == num_of_backends)
1292 /*save pkg type and pkg name for future*/
1293 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1294 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1295 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
1296 memset((item->appid),0,MAX_PKG_NAME_LEN);
1297 ptr->uid = item->uid;
1298 DBG("handle request type [%d]", item->req_type);
1300 switch (item->req_type) {
1301 case PKGMGR_REQUEST_TYPE_INSTALL:
1302 __set_backend_busy(x);
1303 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1304 ret = __process_install(item);
1306 case PKGMGR_REQUEST_TYPE_REINSTALL:
1307 __set_backend_busy(x);
1308 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1309 ret = __process_reinstall(item);
1311 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1312 __set_backend_busy(x);
1313 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1314 ret = __process_uninstall(item);
1316 case PKGMGR_REQUEST_TYPE_MOVE:
1317 __set_backend_busy(x);
1318 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1319 ret = __process_move(item);
1321 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1322 ret = __process_enable_pkg(item);
1324 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1325 ret = __process_disable_pkg(item);
1327 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1328 ret = __process_enable_app(item);
1330 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1331 ret = __process_disable_app(item);
1333 case PKGMGR_REQUEST_TYPE_GETSIZE:
1334 __set_backend_busy(x);
1335 ret = __process_getsize(item);
1337 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1338 __set_backend_busy(x);
1339 ret = __process_cleardata(item);
1341 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1342 __set_backend_busy(x);
1343 ret = __process_clearcache(item);
1345 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1346 ret = __process_enable_global_app_for_uid(item);
1348 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1349 ret = __process_disable_global_app_for_uid(item);
1351 case PKGMGR_REQUEST_TYPE_KILL:
1352 ret = __process_kill(item);
1354 case PKGMGR_REQUEST_TYPE_CHECK:
1355 ret = __process_check(item);
1357 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1358 ret = __process_generate_license_request(item);
1360 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1361 ret = __process_register_license(item);
1363 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1364 ret = __process_decrypt_package(item);
1366 case PKGMGR_REQUEST_TYPE_ADD_BLACKLIST:
1367 ret = __process_add_blacklist(item);
1369 case PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST:
1370 ret = __process_remove_blacklist(item);
1372 case PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST:
1373 ret = __process_check_blacklist(item);
1386 #define IS_WHITESPACE(CHAR) \
1387 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1389 void _app_str_trim(char *input)
1391 char *trim_str = input;
1396 while (*input != 0) {
1397 if (!IS_WHITESPACE(*input)) {
1408 char *_get_backend_cmd(char *type)
1411 char buffer[1024] = { 0 };
1412 char *command = NULL;
1414 fp = fopen(PKG_CONF_PATH, "r");
1420 while (fgets(buffer, 1024, fp) != NULL) {
1421 if (buffer[0] == '#')
1424 _app_str_trim(buffer);
1426 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1427 DBG("buffer [%s]", buffer);
1428 path = path + strlen(PKG_BACKEND);
1429 DBG("path [%s]", path);
1432 (char *)malloc(sizeof(char) * strlen(path) +
1434 if (command == NULL) {
1439 size = strlen(path) + strlen(type) + 1;
1440 snprintf(command, size, "%s%s", path, type);
1441 command[strlen(path) + strlen(type)] = '\0';
1442 DBG("command [%s]", command);
1450 memset(buffer, 0x00, 1024);
1456 return NULL; /* cannot find proper command */
1459 int main(int argc, char *argv[])
1461 FILE *fp_status = NULL;
1462 char buf[32] = { 0, };
1464 char *backend_cmd = NULL;
1465 char *backend_name = NULL;
1468 DBG("server start");
1470 if (argv[1] && (strcmp(argv[1], "init") == 0)) {
1471 /* if current status is "processing",
1472 execute related backend with '-r' option */
1473 if (!(fp_status = fopen(STATUS_FILE, "r")))
1474 return 0; /*if file is not exist, terminated. */
1475 /* if processing <-- unintended termination */
1476 if (fgets(buf, 32, fp_status) &&
1477 strcmp(buf, "processing") == 0) {
1479 if (pid == 0) { /* child */
1480 if (fgets(buf, 32, fp_status))
1481 backend_cmd = _get_backend_cmd(buf);
1482 if (!backend_cmd) { /* if NULL, */
1483 DBG("fail to get backend command");
1487 strrchr(backend_cmd, '/');
1488 if (!backend_name) {
1489 DBG("fail to get backend name");
1493 execl(backend_cmd, backend_name, "-r",
1497 fprintf(fp_status, " ");
1501 } else if (pid < 0) { /* error */
1505 } else { /* parent */
1507 DBG("parent end\n");
1508 fprintf(fp_status, " ");
1515 r = _pm_queue_init();
1517 DBG("Queue Initialization Failed\n");
1521 r = __init_backend_info();
1523 DBG("backend info init failed");
1527 r = __init_request_handler();
1529 ERR("dbus init failed");
1533 if (__register_signal_handler()) {
1534 ERR("failed to register signal handler");
1538 #if !GLIB_CHECK_VERSION(2,35,0)
1541 mainloop = g_main_loop_new(NULL, FALSE);
1543 ERR("g_main_loop_new failed");
1547 DBG("Main loop is created.");
1549 g_main_loop_run(mainloop);
1551 DBG("Quit main loop.");
1552 __fini_request_handler();
1553 __fini_backend_info();
1556 DBG("package manager server terminated.");