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;
340 info.pid = waitpid(-1, &info.status, WNOHANG);
341 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
342 ERR("failed to write result: %s", strerror(errno));
345 static int __register_signal_handler(void)
347 static int sig_reg = 0;
348 struct sigaction act;
353 act.sa_handler = sighandler;
354 sigemptyset(&act.sa_mask);
355 act.sa_flags = SA_NOCLDSTOP;
356 if (sigaction(SIGCHLD, &act, NULL) < 0) {
357 ERR("signal: SIGCHLD failed\n");
361 g_timeout_add_seconds(2, exit_server, NULL);
367 static int __check_backend_status_for_exit(void)
370 for(i = 0; i < num_of_backends; i++)
372 if (!__is_backend_busy(i))
380 static int __check_queue_status_for_exit(void)
382 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
383 queue_info_map *ptr = NULL;
388 for(i = 0; i < entries; i++)
390 if (ptr->queue_slot <= slot) {
396 slot = ptr->queue_slot;
401 for(i = 0; i < num_of_backends; i++)
411 gboolean exit_server(void *data)
413 DBG("exit_server Start\n");
414 if (__check_backend_status_for_exit() &&
415 __check_queue_status_for_exit()) {
416 if (!getenv("PMS_STANDALONE")) {
417 g_main_loop_quit(mainloop);
424 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
428 if (buf == NULL || path == NULL)
430 fd = open(path, O_RDONLY);
433 ret = read(fd, buf, size - 1);
443 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
444 const char *cmdline, const char *apppath)
448 if (strcmp(cmdline, apppath) == 0) {
450 if (pid != getpgid(pid))
456 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
459 struct dirent *dentry;
462 char buf[1024] = {'\0'};
465 dp = opendir("/proc");
470 while ((dentry = readdir(dp)) != NULL) {
471 if (!isdigit(dentry->d_name[0]))
474 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
475 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
479 pid = __pkgcmd_find_pid_by_cmdline(dentry->d_name, buf, apppath);
490 if (killpg(pgid, SIGKILL) < 0) {
502 static void __make_pid_info_file(char *req_key, int pid)
506 char buf[MAX_PKG_TYPE_LEN] = {0};
507 char info_file[PATH_MAX] = {'\0'};
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);
530 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
537 if (handle == NULL) {
538 perror("appinfo handle is NULL\n");
541 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
543 perror("Failed to get app exec path\n");
546 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
548 perror("Failed to get pkgid\n");
552 if (strcmp(user_data, "kill") == 0)
553 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
554 else if(strcmp(user_data, "check") == 0)
555 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
557 __make_pid_info_file(pkgid, pid);
562 void free_user_context(user_ctx* ctx)
569 //env variable ends by NULL element
579 int set_environement(user_ctx *ctx)
586 if (setgid(ctx->gid)) {
587 ERR("setgid failed: %d", errno);
590 if (setuid(ctx->uid)) {
591 ERR("setuid failed: %d", errno);
595 //env variable ends by NULL element
597 if (putenv(env[i]) != 0)
604 user_ctx *get_user_context(uid_t uid)
606 /* we can use getpwnam because this is used only after a
607 * fork and just before an execv
608 * No concurrencial call can corrupt the data
609 * returned by getpwuid
611 user_ctx *context_res;
623 context_res = (user_ctx *)malloc(sizeof(user_ctx));
628 env = (char **)malloc(3 * sizeof(char *));
633 // Build environment context
634 len = snprintf(NULL, 0, "HOME=%s", pwd->pw_dir);
635 env[0] = (char *)malloc((len + 1) * sizeof(char));
640 snprintf(env[0], len + 1, "HOME=%s", pwd->pw_dir);
641 len = snprintf(NULL, 0, "USER=%s", pwd->pw_name);
642 env[1] = (char *)malloc((len + 1) * sizeof(char));
647 snprintf(env[1], len + 1, "USER=%s", pwd->pw_name);
655 //env variable ends by NULL element
656 while (env && env[i]) {
663 context_res->env = env;
664 context_res->uid = uid;
665 context_res->gid = pwd->pw_gid;
670 static char **__generate_argv(const char *args)
672 /* Create args vector
673 * req_id + pkgid + args
675 * vector size = # of args +
676 *(req_id + pkgid + NULL termination = 3)
677 * Last value must be NULL for execv.
685 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
686 if (FALSE == ret_parse) {
687 DBG("Failed to split args: %s", args);
688 DBG("messsage: %s", gerr->message);
693 for (i = 0; i < argcp; i++)
694 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
699 void __set_environment(gpointer user_data)
701 user_ctx *ctx = (user_ctx *)user_data;
703 if (set_environement(ctx))
704 DBG("Failed to set env for the user : %d", ctx->uid);
707 static int __fork_and_exec_with_args(char **argv, uid_t uid)
709 user_ctx* user_context;
710 GError *error = NULL;
714 user_context = get_user_context(uid);
716 DBG("Failed to getenv for the user : %d", uid);
720 ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
721 __set_environment, (gpointer)user_context, &pid,
724 ERR("Failed to excute backend: %s", error->message);
728 free_user_context(user_context);
733 static int __change_item_info(pm_dbus_msg *item, uid_t uid)
737 bool is_global = false;
738 pkgmgrinfo_appinfo_h handle = NULL;
740 switch (item->req_type) {
741 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
742 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
743 ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle);
746 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
747 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
748 ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle);
752 return PMINFO_R_ERROR;
755 if (ret != PMINFO_R_OK)
756 return PMINFO_R_ERROR;
758 ret = pkgmgrinfo_appinfo_is_global(handle, &is_global);
759 if (ret != PMINFO_R_OK)
762 if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_APP
763 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_APP)
765 ret = PMINFO_R_ERROR;
767 } else if ((item->req_type == PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID
768 || item->req_type == PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
770 ret = PMINFO_R_ERROR;
774 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
775 if (ret != PMINFO_R_OK)
778 strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1);
779 memset((item->pkgid),0,MAX_PKG_NAME_LEN);
780 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
783 pkgmgrinfo_appinfo_destroy_appinfo(handle);
788 static int __process_install(pm_dbus_msg *item)
792 char args[MAX_PKG_ARGS_LEN] = {'\0', };
795 backend_cmd = _get_backend_cmd(item->pkg_type);
796 if (backend_cmd == NULL)
799 snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd,
800 item->req_id, item->pkgid, item->args);
802 argv = __generate_argv(args);
804 pid = __fork_and_exec_with_args(argv, item->uid);
811 static int __process_reinstall(pm_dbus_msg *item)
815 char args[MAX_PKG_ARGS_LEN];
818 backend_cmd = _get_backend_cmd(item->pkg_type);
819 if (backend_cmd == NULL)
822 snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
823 item->req_id, item->pkgid);
824 argv = __generate_argv(args);
826 pid = __fork_and_exec_with_args(argv, item->uid);
834 static int __process_uninstall(pm_dbus_msg *item)
838 char args[MAX_PKG_ARGS_LEN];
841 backend_cmd = _get_backend_cmd(item->pkg_type);
842 if (backend_cmd == NULL)
845 snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
846 item->req_id, item->pkgid);
847 argv = __generate_argv(args);
849 pid = __fork_and_exec_with_args(argv, item->uid);
857 static int __process_move(pm_dbus_msg *item)
861 char args[MAX_PKG_ARGS_LEN];
864 backend_cmd = _get_backend_cmd(item->pkg_type);
865 if (backend_cmd == NULL)
868 /* TODO: set movetype */
869 snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
870 item->req_id, item->pkgid, item->args);
871 argv = __generate_argv(args);
873 pid = __fork_and_exec_with_args(argv, item->uid);
881 static int __process_enable_pkg(pm_dbus_msg *item)
887 static int __process_disable_pkg(pm_dbus_msg *item)
893 static int __process_enable_app(pm_dbus_msg *item)
897 __send_app_signal(item->uid, item->req_id, item->pkg_type,
898 item->pkgid, item->pkgid,
899 PKGMGR_INSTALLER_START_KEY_STR,
900 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR);
902 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
903 ret = __change_item_info(item, item->uid);
904 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
905 __send_app_signal(item->uid, item->req_id, item->pkg_type,
906 item->pkgid, item->pkgid,
907 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
911 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0);
912 if (ret != PMINFO_R_OK)
913 __send_app_signal(item->uid, item->req_id, item->pkg_type,
914 item->pkgid, item->appid,
915 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
917 __send_app_signal(item->uid, item->req_id, item->pkg_type,
918 item->pkgid, item->appid,
919 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
924 static int __process_disable_app(pm_dbus_msg *item)
928 __send_app_signal(item->uid, item->req_id, item->pkg_type,
929 item->pkgid, item->pkgid,
930 PKGMGR_INSTALLER_START_KEY_STR,
931 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR);
933 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
934 ret = __change_item_info(item, item->uid);
935 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
936 __send_app_signal(item->uid, item->req_id, item->pkg_type,
937 item->pkgid, item->pkgid,
938 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
942 ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1);
943 if (ret != PMINFO_R_OK)
944 __send_app_signal(item->uid, item->req_id, item->pkg_type,
945 item->pkgid, item->appid,
946 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
948 __send_app_signal(item->uid, item->req_id, item->pkg_type,
949 item->pkgid, item->appid,
950 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
955 static int __process_enable_global_app_for_uid(pm_dbus_msg *item)
959 __send_app_signal(item->uid, item->req_id, item->pkg_type,
960 item->pkgid, item->pkgid,
961 PKGMGR_INSTALLER_START_KEY_STR,
962 PKGMGR_INSTALLER_GLOBAL_APP_ENABLE_FOR_UID);
964 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
965 ret = __change_item_info(item, item->uid);
966 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
967 __send_app_signal(item->uid, item->req_id, item->pkg_type,
968 item->pkgid, item->pkgid,
969 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
973 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0);
974 if (ret != PMINFO_R_OK)
975 __send_app_signal(item->uid, item->req_id, item->pkg_type,
976 item->pkgid, item->appid,
977 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
979 __send_app_signal(item->uid, item->req_id, item->pkg_type,
980 item->pkgid, item->appid,
981 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
986 static int __process_disable_global_app_for_uid(pm_dbus_msg *item)
990 __send_app_signal(item->uid, item->req_id, item->pkg_type,
991 item->pkgid, item->pkgid,
992 PKGMGR_INSTALLER_START_KEY_STR,
993 PKGMGR_INSTALLER_GLOBAL_APP_DISABLE_FOR_UID);
995 /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */
996 ret = __change_item_info(item, GLOBAL_USER);
997 if (ret != PMINFO_R_OK || strlen(item->appid) == 0) {
998 __send_app_signal(item->uid, item->req_id, item->pkg_type,
999 item->pkgid, item->pkgid,
1000 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1004 ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 1);
1005 if (ret != PMINFO_R_OK)
1006 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1007 item->pkgid, item->appid,
1008 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_FAIL_EVENT_STR);
1010 __send_app_signal(item->uid, item->req_id, item->pkg_type,
1011 item->pkgid, item->appid,
1012 PKGMGR_INSTALLER_END_KEY_STR, PKGMGR_INSTALLER_OK_EVENT_STR);
1017 static int __process_getsize(pm_dbus_msg *item)
1019 static const char *backend_cmd = "/usr/bin/pkg_getsize";
1021 char args[MAX_PKG_ARGS_LEN];
1024 snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid,
1025 item->args, item->req_id);
1026 argv = __generate_argv(args);
1027 pid = __fork_and_exec_with_args(argv, item->uid);
1034 static int __process_cleardata(pm_dbus_msg *item)
1038 char args[MAX_PKG_ARGS_LEN];
1041 backend_cmd = _get_backend_cmd(item->pkg_type);
1042 if (backend_cmd == NULL)
1045 /* TODO: set movetype */
1046 snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
1047 item->req_id, item->pkgid);
1048 argv = __generate_argv(args);
1050 pid = __fork_and_exec_with_args(argv, item->uid);
1058 static int __process_clearcache(pm_dbus_msg *item)
1060 static const char *backend_cmd = "/usr/bin/pkg_clearcache";
1062 char args[MAX_PKG_ARGS_LEN];
1065 snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid);
1066 argv = __generate_argv(args);
1067 pid = __fork_and_exec_with_args(argv, item->uid);
1074 static int __process_kill(pm_dbus_msg *item)
1077 pkgmgrinfo_pkginfo_h handle;
1079 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1082 ERR("Failed to get handle");
1086 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1087 __pkgcmd_app_cb, "kill", item->uid);
1088 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1090 ERR("pkgmgrinfo_appinfo_get_list() failed");
1097 static int __process_check(pm_dbus_msg *item)
1100 pkgmgrinfo_pkginfo_h handle;
1102 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
1105 ERR("Failed to get handle");
1109 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1110 __pkgcmd_app_cb, "check", item->uid);
1111 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1113 ERR("pkgmgrinfo_appinfo_get_list() failed");
1120 static int __process_generate_license_request(pm_dbus_msg *item)
1124 char req_data[MAX_PKG_ARGS_LEN];
1125 unsigned int req_data_len;
1126 char license_url[MAX_PKG_ARGS_LEN];
1127 unsigned int license_url_len;
1129 resp_data = item->args;
1130 req_data_len = sizeof(req_data);
1131 license_url_len = sizeof(license_url);
1133 ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1134 req_data, &req_data_len, license_url, &license_url_len);
1135 if (ret != TADC_SUCCESS) {
1136 ERR("drm_tizen_generate_license_request failed: %d", ret);
1137 __return_value_to_caller(item->req_id, g_variant_new("(iss)",
1138 PKGMGR_R_ESYSTEM, "", ""));
1142 __return_value_to_caller(item->req_id,
1143 g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1149 static int __process_register_license(pm_dbus_msg *item)
1154 resp_data = item->args;
1156 ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1157 if (ret != TADC_SUCCESS) {
1158 ERR("drm_tizen_register_license failed: %d", ret);
1159 __return_value_to_caller(item->req_id,
1160 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1164 __return_value_to_caller(item->req_id,
1165 g_variant_new("(i)", PKGMGR_R_OK));
1170 static int __process_decrypt_package(pm_dbus_msg *item)
1173 char *drm_file_path;
1174 char *decrypted_file_path;
1176 drm_file_path = item->pkgid;
1177 decrypted_file_path = item->args;
1179 /* TODO: check ownership of decrypted file */
1180 ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1181 decrypted_file_path, strlen(decrypted_file_path));
1182 if (ret != TADC_SUCCESS) {
1183 ERR("drm_tizen_register_license failed: %d", ret);
1184 __return_value_to_caller(item->req_id,
1185 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1189 __return_value_to_caller(item->req_id,
1190 g_variant_new("(i)", PKGMGR_R_OK));
1195 static int __process_add_blacklist(pm_dbus_msg *item)
1199 ret = __add_blacklist(item->uid, item->pkgid);
1201 __return_value_to_caller(item->req_id,
1202 g_variant_new("(i)", ret));
1207 static int __process_remove_blacklist(pm_dbus_msg *item)
1211 ret = __remove_blacklist(item->uid, item->pkgid);
1213 __return_value_to_caller(item->req_id,
1214 g_variant_new("(i)", ret));
1219 static int __process_check_blacklist(pm_dbus_msg *item)
1224 ret = __check_blacklist(item->uid, item->pkgid, &result);
1226 __return_value_to_caller(item->req_id,
1227 g_variant_new("(ii)", result, ret));
1232 gboolean queue_job(void *data)
1234 pm_dbus_msg *item = NULL;
1239 /* Pop a job from queue */
1240 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1241 if (__is_backend_busy(x))
1244 item = _pm_queue_pop(x);
1245 if (item && item->req_type != -1)
1250 /* all backend messages queue are empty or busy */
1251 if (x == num_of_backends)
1254 /*save pkg type and pkg name for future*/
1255 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1256 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1257 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
1258 memset((item->appid),0,MAX_PKG_NAME_LEN);
1259 ptr->uid = item->uid;
1260 DBG("handle request type [%d]", item->req_type);
1262 switch (item->req_type) {
1263 case PKGMGR_REQUEST_TYPE_INSTALL:
1264 __set_backend_busy(x);
1265 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1266 ret = __process_install(item);
1268 case PKGMGR_REQUEST_TYPE_REINSTALL:
1269 __set_backend_busy(x);
1270 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1271 ret = __process_reinstall(item);
1273 case PKGMGR_REQUEST_TYPE_UNINSTALL:
1274 __set_backend_busy(x);
1275 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1276 ret = __process_uninstall(item);
1278 case PKGMGR_REQUEST_TYPE_MOVE:
1279 __set_backend_busy(x);
1280 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1281 ret = __process_move(item);
1283 case PKGMGR_REQUEST_TYPE_ENABLE_PKG:
1284 ret = __process_enable_pkg(item);
1286 case PKGMGR_REQUEST_TYPE_DISABLE_PKG:
1287 ret = __process_disable_pkg(item);
1289 case PKGMGR_REQUEST_TYPE_ENABLE_APP:
1290 ret = __process_enable_app(item);
1292 case PKGMGR_REQUEST_TYPE_DISABLE_APP:
1293 ret = __process_disable_app(item);
1295 case PKGMGR_REQUEST_TYPE_GETSIZE:
1296 __set_backend_busy(x);
1297 ret = __process_getsize(item);
1299 case PKGMGR_REQUEST_TYPE_CLEARDATA:
1300 __set_backend_busy(x);
1301 ret = __process_cleardata(item);
1303 case PKGMGR_REQUEST_TYPE_CLEARCACHE:
1304 __set_backend_busy(x);
1305 ret = __process_clearcache(item);
1307 case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1308 ret = __process_enable_global_app_for_uid(item);
1310 case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1311 ret = __process_disable_global_app_for_uid(item);
1313 case PKGMGR_REQUEST_TYPE_KILL:
1314 ret = __process_kill(item);
1316 case PKGMGR_REQUEST_TYPE_CHECK:
1317 ret = __process_check(item);
1319 case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1320 ret = __process_generate_license_request(item);
1322 case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE:
1323 ret = __process_register_license(item);
1325 case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE:
1326 ret = __process_decrypt_package(item);
1328 case PKGMGR_REQUEST_TYPE_ADD_BLACKLIST:
1329 ret = __process_add_blacklist(item);
1331 case PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST:
1332 ret = __process_remove_blacklist(item);
1334 case PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST:
1335 ret = __process_check_blacklist(item);
1348 #define IS_WHITESPACE(CHAR) \
1349 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1351 void _app_str_trim(char *input)
1353 char *trim_str = input;
1358 while (*input != 0) {
1359 if (!IS_WHITESPACE(*input)) {
1370 char *_get_backend_cmd(char *type)
1373 char buffer[1024] = { 0 };
1374 char *command = NULL;
1376 fp = fopen(PKG_CONF_PATH, "r");
1382 while (fgets(buffer, 1024, fp) != NULL) {
1383 if (buffer[0] == '#')
1386 _app_str_trim(buffer);
1388 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1389 DBG("buffer [%s]", buffer);
1390 path = path + strlen(PKG_BACKEND);
1391 DBG("path [%s]", path);
1394 (char *)malloc(sizeof(char) * strlen(path) +
1396 if (command == NULL) {
1401 size = strlen(path) + strlen(type) + 1;
1402 snprintf(command, size, "%s%s", path, type);
1403 command[strlen(path) + strlen(type)] = '\0';
1404 DBG("command [%s]", command);
1412 memset(buffer, 0x00, 1024);
1418 return NULL; /* cannot find proper command */
1421 int main(int argc, char *argv[])
1423 FILE *fp_status = NULL;
1424 char buf[32] = { 0, };
1426 char *backend_cmd = NULL;
1427 char *backend_name = NULL;
1430 DBG("server start");
1432 if (argv[1] && (strcmp(argv[1], "init") == 0)) {
1433 /* if current status is "processing",
1434 execute related backend with '-r' option */
1435 if (!(fp_status = fopen(STATUS_FILE, "r")))
1436 return 0; /*if file is not exist, terminated. */
1437 /* if processing <-- unintended termination */
1438 if (fgets(buf, 32, fp_status) &&
1439 strcmp(buf, "processing") == 0) {
1441 if (pid == 0) { /* child */
1442 if (fgets(buf, 32, fp_status))
1443 backend_cmd = _get_backend_cmd(buf);
1444 if (!backend_cmd) { /* if NULL, */
1445 DBG("fail to get backend command");
1449 strrchr(backend_cmd, '/');
1450 if (!backend_name) {
1451 DBG("fail to get backend name");
1455 execl(backend_cmd, backend_name, "-r",
1459 fprintf(fp_status, " ");
1463 } else if (pid < 0) { /* error */
1467 } else { /* parent */
1469 DBG("parent end\n");
1470 fprintf(fp_status, " ");
1477 r = _pm_queue_init();
1479 DBG("Queue Initialization Failed\n");
1483 r = __init_backend_info();
1485 DBG("backend info init failed");
1489 r = __init_request_handler();
1491 ERR("dbus init failed");
1495 if (__register_signal_handler()) {
1496 ERR("failed to register signal handler");
1500 #if !GLIB_CHECK_VERSION(2,35,0)
1503 mainloop = g_main_loop_new(NULL, FALSE);
1505 ERR("g_main_loop_new failed");
1509 DBG("Main loop is created.");
1511 g_main_loop_run(mainloop);
1513 DBG("Quit main loop.");
1514 __fini_request_handler();
1515 __fini_backend_info();
1518 DBG("package manager server terminated.");