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>
39 #include <pkgmgr-info.h>
40 #include <pkgmgr/pkgmgr_parser.h>
41 #include <cynara-client.h>
42 #include <tzplatform_config.h>
44 #include "pkgmgr_installer.h"
45 #include "comm_pkg_mgr_server.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)
57 static int backend_flag = 0; /* 0 means that backend process is not running */
67 8 bit value to represent maximum 8 backends.
68 Each bit position corresponds to a queue slot which
69 is dynamically determined.
71 char backend_busy = 0;
73 8 bit value to represent quiet mode operation for maximum 8 backends
75 Each bit position corresponds to a queue slot which
76 is dynamically determined.
78 char backend_mode = 63; /*00111111*/
79 extern int num_of_backends;
81 struct signal_info_t {
86 static int pipe_sig[2];
87 static GIOChannel *pipe_io;
88 static guint pipe_wid;
91 extern queue_info_map *start;
93 static cynara *p_cynara;
95 GMainLoop *mainloop = NULL;
100 OPERATION_INSTALL = 0,
111 }pkgmgr_svc_app_component;
113 static int __check_backend_status_for_exit(void);
114 static int __check_queue_status_for_exit(void);
115 static int __is_backend_busy(int position);
116 static void __set_backend_busy(int position);
117 static void __set_backend_free(int position);
118 static void __set_backend_mode(int position);
119 static void __unset_backend_mode(int position);
120 static void sighandler(int signo);
121 static int __get_position_from_pkg_type(char *pkgtype);
122 static int __is_efl_tpk_app(char *pkgpath);
123 static int __xsystem(const char *argv[]);
125 gboolean queue_job(void *data);
126 gboolean exit_server(void *data);
128 /* To check whether a particular backend is free/busy*/
129 static int __is_backend_busy(int position)
131 return backend_busy & 1<<position;
133 /*To set a particular backend as busy*/
134 static void __set_backend_busy(int position)
136 backend_busy = backend_busy | 1<<position;
138 /*To set a particular backend as free */
139 static void __set_backend_free(int position)
141 backend_busy = backend_busy & ~(1<<position);
143 /*To set a particular backend mode as quiet*/
144 static void __set_backend_mode(int position)
146 backend_mode = backend_mode | 1<<position;
148 /*To unset a particular backend mode */
149 static void __unset_backend_mode(int position)
151 backend_mode = backend_mode & ~(1<<position);
154 static int __is_global(uid_t uid)
156 return (uid == OWNER_ROOT || uid == GLOBAL_USER) ? 1 : 0;
159 static const char *__get_recovery_file_path(uid_t uid)
163 if (!__is_global(uid))
164 tzplatform_set_user(uid);
166 path = tzplatform_getenv(__is_global(uid)
167 ? TZ_SYS_RW_PACKAGES : TZ_USER_PACKAGES);
169 tzplatform_reset_user();
174 static void __set_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
176 char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
177 char buffer[MAX_PKG_NAME_LEN] = { 0 };
178 char *pkgid_tmp = NULL;
179 FILE *rev_file = NULL;
182 DBG("pkgid is null\n");
186 /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
187 if (strstr(pkgid, "/")) {
188 pkgid_tmp = strrchr(pkgid, '/') + 1;
189 if (pkgid_tmp == NULL) {
190 DBG("pkgid_tmp[%s] is null\n", pkgid);
193 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
195 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
198 rev_file = fopen(recovery_file, "w");
199 if (rev_file== NULL) {
200 DBG("rev_file[%s] is null\n", recovery_file);
204 snprintf(buffer, MAX_PKG_NAME_LEN, "pkgid : %s\n", pkgid);
205 fwrite(buffer, sizeof(char), strlen(buffer), rev_file);
210 static void __unset_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
213 char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
214 char *pkgid_tmp = NULL;
217 DBG("pkgid is null\n");
221 /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
222 if (strstr(pkgid, "/")) {
223 pkgid_tmp = strrchr(pkgid, '/') + 1;
224 if (pkgid_tmp == NULL) {
225 DBG("pkgid_tmp[%s] is null\n", pkgid);
228 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
230 snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
233 ret = remove(recovery_file);
235 DBG("remove recovery_file[%s] fail\n", recovery_file);
238 #define PRIVILEGE_PACKAGEMANAGER_ADMIN "http://tizen.org/privilege/packagemanager.admin"
239 #define PRIVILEGE_PACKAGEMANAGER_INFO "http://tizen.org/privilege/packagemanager.info"
240 #define PRIVILEGE_PACKAGEMANAGER_NONE "NONE"
242 static const char *__convert_req_type_to_privilege(int req_type)
245 case COMM_REQ_TO_INSTALLER:
246 case COMM_REQ_TO_ACTIVATOR:
247 case COMM_REQ_TO_CLEARER:
248 case COMM_REQ_TO_MOVER:
249 case COMM_REQ_KILL_APP:
250 case COMM_REQ_CLEAR_CACHE_DIR:
251 return PRIVILEGE_PACKAGEMANAGER_ADMIN;
252 case COMM_REQ_GET_SIZE:
253 case COMM_REQ_CHECK_APP:
254 return PRIVILEGE_PACKAGEMANAGER_INFO;
255 case COMM_REQ_CANCEL:
257 return PRIVILEGE_PACKAGEMANAGER_NONE;
261 static int __check_privilege_by_cynara(const char *client, const char *session, const char *user, int req_type)
264 const char *privilege;
265 char buf[BUFMAX] = {0, };
267 privilege = __convert_req_type_to_privilege(req_type);
268 if (!strcmp(privilege, PRIVILEGE_PACKAGEMANAGER_NONE))
271 ret = cynara_check(p_cynara, client, session, user, privilege);
273 case CYNARA_API_ACCESS_ALLOWED:
274 DBG("%s(%s) from user %s privilege %s allowed", client, session, user, privilege);
276 case CYNARA_API_ACCESS_DENIED:
277 ERR("%s(%s) from user %s privilege %s denied", client, session, user, privilege);
280 cynara_strerror(ret, buf, BUFMAX);
281 ERR("cynara_check failed: %s", buf);
286 static int __get_position_from_pkg_type(char *pkgtype)
291 for(i = 0; i < entries; i++)
293 if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
294 return ptr->queue_slot;
302 static int __xsystem(const char *argv[])
312 DBG("fork() failed");
315 if (execvp(argv[0], (char *const *)argv) == -1) {
316 DBG("execvp() failed");
322 err = waitpid(pid, &status, WUNTRACED | WCONTINUED);
324 DBG("waitpid failed\n");
327 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
330 if (WIFEXITED(status))
331 return WEXITSTATUS(status);
336 static int __is_efl_tpk_app(char *pkgid)
340 const char *unzip_argv[] = { "/usr/bin/unzip", "-j", pkgid, "usr/share/packages/*", "-d", "/tmp/efltpk-unzip", NULL };
341 const char *unzip_opt_argv[] = { "/usr/bin/unzip", "-j", pkgid, "opt/share/packages/*", "-d", "/tmp/efltpk-unzip", NULL };
342 const char *delete_argv[] = { "/bin/rm", "-rf", "/tmp/efltpk-unzip", NULL };
343 pkgmgrinfo_pkginfo_h handle;
344 /*Check for uninstall case. If we fail to get handle then request is for installation*/
345 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
346 if (ret == PMINFO_R_OK) {
347 ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
348 if (ret != PMINFO_R_OK) {
349 DBG("Failed to get package type\n");
350 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
353 if (strcmp(type, "efltpk") == 0) {
354 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
357 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
362 if (strstr(pkgid, ".tpk") == NULL) {
366 __xsystem(delete_argv);
367 ret = mkdir("/tmp/efltpk-unzip", 0755);
369 DBG("Failed to create temporary directory to unzip tpk package\n");
372 /*In case of installation request, pkgid contains the pkgpath*/
373 ret = __xsystem(unzip_argv);
375 ret = __xsystem(unzip_opt_argv);
377 DBG("Unzip of tpk package failed. error:%d\n", ret);
378 if (ret == NO_MATCHING_FILE) /*no matching file found*/
388 __xsystem(delete_argv);
392 static void send_fail_signal(char *pname, char *ptype, char *args)
394 DBG("send_fail_signal start\n");
399 pkgmgr_installer *pi;
400 pi = pkgmgr_installer_new();
402 DBG("Failure in creating the pkgmgr_installer object");
405 ret_parse = g_shell_parse_argv(args,
406 &argcp, &argvp, &gerr);
407 if (FALSE == ret_parse) {
408 DBG("Failed to split args: %s", args);
409 DBG("messsage: %s", gerr->message);
410 pkgmgr_installer_free(pi);
414 pkgmgr_installer_receive_request(pi, argcp, argvp);
415 pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
416 pkgmgr_installer_free(pi);
420 static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
426 struct signal_info_t info;
427 backend_info *ptr = begin;
429 s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
430 if (s != G_IO_STATUS_NORMAL) {
431 ERR("Signal pipe read failed: %s", err->message);
436 for (x = 0; x < num_of_backends; x++, ptr++) {
437 if (ptr && ptr->pid == info.pid)
441 if (x == num_of_backends) {
442 ERR("Unknown child exit");
446 __set_backend_free(x);
447 __set_backend_mode(x);
448 __unset_recovery_mode(ptr->uid, ptr->pkgid, ptr->pkgtype);
449 if (WIFSIGNALED(info.status) || WEXITSTATUS(info.status)) {
450 send_fail_signal(ptr->pkgid, ptr->pkgtype, ptr->args);
451 DBG("backend[%s] exit with error", ptr->pkgtype);
453 DBG("backend[%s] exit", ptr->pkgtype);
456 g_idle_add(queue_job, NULL);
461 static int __init_backend_info(void)
465 /*Allocate memory for holding pid, pkgtype and pkgid*/
466 ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
468 DBG("Malloc Failed\n");
473 if (pipe(pipe_sig)) {
474 ERR("create pipe failed");
478 pipe_io = g_io_channel_unix_new(pipe_sig[0]);
479 g_io_channel_set_encoding(pipe_io, NULL, NULL);
480 g_io_channel_set_buffered(pipe_io, FALSE);
481 pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
486 static void __fini_backend_info(void)
488 g_source_remove(pipe_wid);
489 g_io_channel_unref(pipe_io);
493 /*Free backend info */
497 static void sighandler(int signo)
499 struct signal_info_t info;
501 info.pid = waitpid(-1, &info.status, WNOHANG);
502 if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
503 ERR("failed to write result: %s", strerror(errno));
506 static int __register_signal_handler(void)
508 static int sig_reg = 0;
509 struct sigaction act;
514 act.sa_handler = sighandler;
515 sigemptyset(&act.sa_mask);
516 act.sa_flags = SA_NOCLDSTOP;
517 if (sigaction(SIGCHLD, &act, NULL) < 0) {
518 ERR("signal: SIGCHLD failed\n");
522 g_timeout_add_seconds(2, exit_server, NULL);
528 void req_cb(void *cb_data, uid_t uid, const char *req_id, const int req_type,
529 const char *pkg_type, const char *pkgid, const char *args,
530 const char *client, const char *session, const char *user, int *ret)
534 DBG(">> in callback >> Got request: [%s] [%d] [%s] [%s] [%s] [%s] [%s] [%s]",
535 req_id, req_type, pkg_type, pkgid, args, client, session, user);
537 pm_dbus_msg *item = calloc(1, sizeof(pm_dbus_msg));
538 memset(item, 0x00, sizeof(pm_dbus_msg));
540 strncpy(item->req_id, req_id, sizeof(item->req_id) - 1);
541 item->req_type = req_type;
542 strncpy(item->pkg_type, pkg_type, sizeof(item->pkg_type) - 1);
543 strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1);
544 strncpy(item->args, args, sizeof(item->args) - 1);
546 /* uid equals to GLOBALUSER means that the installation or action is made at Global level.
547 * At this time, we are not able to check the credentials of this dbus message (due to gdbus API to implement the pkgmgr-server)
548 * So we cannot check if the user that makes request has permisssion to do it.
549 * Note theses CAPI could be used by deamon (user is root or system user) or web/native API framework (user id is one of regular users)
550 * In consequence a bug is filed :
552 * Logic has to be implmemented:
553 * RUID means the id of the user that make the request (retreived from credential of the message)
554 * UID is the uid in argument of the request
556 * if RUID == UID & UID is regular user == TRUE ==> Granted
557 * if UID == GLOBAL_USER & RUID is ADMIN == TRUE ==> Granted
558 * if RUID == (ROOT or System USER) & UID is Regular USER ==> Granted
559 * if UID != Regular USER & UID != GLOBAL USER == TRUE ==> NOT GRANTED
560 * if RUID == Regular USER & UID != RUID == True ==> NOT GRANTED
563 if (__register_signal_handler()) {
564 ERR("failed to register signal handler");
565 *ret = COMM_RET_ERROR;
568 g_idle_add(queue_job, NULL);
570 DBG("req_type=(%d) backend_flag=(%d)\n", req_type, backend_flag);
572 if (__check_privilege_by_cynara(client, session, user, item->req_type)) {
573 *ret = PKGMGR_R_EPRIV;
577 switch (item->req_type) {
578 case COMM_REQ_TO_INSTALLER:
580 if (_pm_queue_push(item)) {
581 ERR("failed to push queue item");
582 *ret = COMM_RET_ERROR;
585 p = __get_position_from_pkg_type(item->pkg_type);
586 __set_backend_mode(p);
591 case COMM_REQ_TO_ACTIVATOR:
592 /* In case of activate, there is no popup */
593 if (_pm_queue_push(item)) {
594 ERR("failed to push queue item");
595 *ret = COMM_RET_ERROR;
598 p = __get_position_from_pkg_type(item->pkg_type);
599 __set_backend_mode(p);
605 case COMM_REQ_TO_CLEARER:
606 /* In case of clearer, there is no popup */
607 if (_pm_queue_push(item)) {
608 ERR("failed to push queue item");
609 *ret = COMM_RET_ERROR;
612 p = __get_position_from_pkg_type(item->pkg_type);
613 /*the backend shows the success/failure popup
614 so this request is non quiet*/
615 __unset_backend_mode(p);
621 case COMM_REQ_TO_MOVER:
622 /* In case of mover, there is no popup */
623 if (_pm_queue_push(item)) {
624 ERR("failed to push queue item");
625 *ret = COMM_RET_ERROR;
628 p = __get_position_from_pkg_type(item->pkg_type);
629 /*the backend shows the success/failure popup
630 so this request is non quiet*/
631 __unset_backend_mode(p);
636 case COMM_REQ_CANCEL:
637 _pm_queue_delete(item);
638 p = __get_position_from_pkg_type(item->pkg_type);
639 __unset_backend_mode(p);
643 case COMM_REQ_GET_SIZE:
644 if (_pm_queue_push(item)) {
645 ERR("failed to push queue item");
646 *ret = COMM_RET_ERROR;
649 p = __get_position_from_pkg_type(item->pkg_type);
650 __set_backend_mode(p);
656 case COMM_REQ_CHECK_APP:
657 case COMM_REQ_KILL_APP:
658 /* In case of activate, there is no popup */
659 if (_pm_queue_push(item)) {
660 ERR("failed to push queue item");
661 *ret = COMM_RET_ERROR;
664 p = __get_position_from_pkg_type(item->pkg_type);
665 __set_backend_mode(p);
671 case COMM_REQ_CLEAR_CACHE_DIR:
672 if (_pm_queue_push(item)) {
673 ERR("failed to push queue item");
674 *ret = COMM_RET_ERROR;
677 p = __get_position_from_pkg_type(item->pkg_type);
678 __set_backend_mode(p);
684 DBG("Check your request..\n");
685 *ret = COMM_RET_ERROR;
689 if (*ret != COMM_RET_OK) {
690 DBG("Failed to handle request %s %s\n",item->pkg_type, item->pkgid);
691 pkgmgr_installer *pi;
697 pi = pkgmgr_installer_new();
699 DBG("Failure in creating the pkgmgr_installer object");
704 ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
705 if (FALSE == ret_parse) {
706 DBG("Failed to split args: %s", args);
707 DBG("messsage: %s", gerr->message);
708 pkgmgr_installer_free(pi);
713 pkgmgr_installer_receive_request(pi, argcp, argvp);
715 pkgmgr_installer_send_signal(pi, item->pkg_type,
719 pkgmgr_installer_free(pi);
725 static int __check_backend_status_for_exit(void)
728 for(i = 0; i < num_of_backends; i++)
730 if (!__is_backend_busy(i))
738 static int __check_queue_status_for_exit(void)
740 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
741 queue_info_map *ptr = NULL;
746 for(i = 0; i < entries; i++)
748 if (ptr->queue_slot <= slot) {
754 slot = ptr->queue_slot;
759 for(i = 0; i < num_of_backends; i++)
769 gboolean exit_server(void *data)
771 DBG("exit_server Start\n");
772 if (__check_backend_status_for_exit() &&
773 __check_queue_status_for_exit()) {
774 if (!getenv("PMS_STANDALONE")) {
775 g_main_loop_quit(mainloop);
782 static int __pkgcmd_read_proc(const char *path, char *buf, int size)
786 if (buf == NULL || path == NULL)
788 fd = open(path, O_RDONLY);
791 ret = read(fd, buf, size - 1);
801 static int __pkgcmd_find_pid_by_cmdline(const char *dname,
802 const char *cmdline, const char *apppath)
806 if (strcmp(cmdline, apppath) == 0) {
808 if (pid != getpgid(pid))
814 static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
817 struct dirent *dentry;
820 char buf[1024] = {'\0'};
823 dp = opendir("/proc");
828 while ((dentry = readdir(dp)) != NULL) {
829 if (!isdigit(dentry->d_name[0]))
832 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
833 ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
837 pid = __pkgcmd_find_pid_by_cmdline(dentry->d_name, buf, apppath);
848 if (killpg(pgid, SIGKILL) < 0) {
860 static void __make_pid_info_file(char *req_key, int pid)
864 char buf[MAX_PKG_TYPE_LEN] = {0};
865 char info_file[PATH_MAX] = {'\0'};
870 snprintf(info_file, PATH_MAX, "/tmp/%s", req_key);
872 DBG("info_path(%s)", info_file);
873 file = fopen(info_file, "w");
875 ERR("Couldn't open the file(%s)", info_file);
879 snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
880 fwrite(buf, 1, strlen(buf), file);
888 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
895 if (handle == NULL) {
896 perror("appinfo handle is NULL\n");
899 ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
901 perror("Failed to get app exec path\n");
904 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
906 perror("Failed to get pkgid\n");
910 if (strcmp(user_data, "kill") == 0)
911 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
912 else if(strcmp(user_data, "check") == 0)
913 pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
915 __make_pid_info_file(pkgid, pid);
920 void free_user_context(user_ctx* ctx)
927 //env variable ends by NULL element
937 int set_environement(user_ctx *ctx)
944 if (setgid(ctx->gid)) {
945 ERR("setgid failed: %d", errno);
948 if (setuid(ctx->uid)) {
949 ERR("setuid failed: %d", errno);
953 //env variable ends by NULL element
955 if (putenv(env[i]) != 0)
962 user_ctx* get_user_context(uid_t uid)
964 /* we can use getpwnam because this is used only after a
965 * fork and just before an execv
966 * No concurrencial call can corrupt the data
967 * returned by getpwuid
969 user_ctx *context_res;
980 context_res = (user_ctx *)malloc(sizeof(user_ctx));
985 env = (char**)malloc(3* sizeof(char *));
990 // Build environment context
991 len = snprintf(NULL,0, "HOME=%s", pwd->pw_dir);
992 env[0] = (char*)malloc((len + 1)* sizeof(char));
997 sprintf(env[0], "HOME=%s", pwd->pw_dir);
998 len = snprintf(NULL,0, "USER=%s", pwd->pw_name);
999 env[1] = (char*)malloc((len + 1)* sizeof(char));
1000 if(env[1] == NULL) {
1005 sprintf(env[1], "USER=%s", pwd->pw_name);
1013 //env variable ends by NULL element
1021 context_res->env = env;
1022 context_res->uid = uid;
1023 context_res->gid = pwd->pw_gid;
1028 static char **__generate_argv(const char *args)
1030 /* Create args vector
1031 * req_id + pkgid + args
1033 * vector size = # of args +
1034 *(req_id + pkgid + NULL termination = 3)
1035 * Last value must be NULL for execv.
1040 GError *gerr = NULL;
1041 ret_parse = g_shell_parse_argv(args,
1042 &argcp, &argvp, &gerr);
1043 if (FALSE == ret_parse) {
1044 DBG("Failed to split args: %s", args);
1045 DBG("messsage: %s", gerr->message);
1049 /* Setup argument !!! */
1050 /*char **args_vector =
1051 calloc(argcp + 4, sizeof(char *)); */
1052 char **args_vector = calloc(argcp + 1, sizeof(char *));
1053 if (args_vector == NULL) {
1054 ERR("Out of memory");
1057 /*args_vector[0] = strdup(backend_cmd);
1058 args_vector[1] = strdup(item->req_id);
1059 args_vector[2] = strdup(item->pkgid); */
1061 for (arg_idx = 0; arg_idx < argcp; arg_idx++) {
1062 /* args_vector[arg_idx+3] = argvp[arg_idx]; */
1063 args_vector[arg_idx] = argvp[arg_idx];
1067 /*for(arg_idx = 0; arg_idx < argcp+3; arg_idx++) { */
1068 for (arg_idx = 0; arg_idx < argcp + 1; arg_idx++) {
1069 DBG(">>>>>> args_vector[%d]=%s",
1070 arg_idx, args_vector[arg_idx]);
1076 static void __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid)
1078 user_ctx* user_context = get_user_context(uid);
1080 DBG("Failed to getenv for the user : %d", uid);
1083 if(set_environement(user_context)){
1084 DBG("Failed to set env for the user : %d", uid);
1087 free_user_context(user_context);
1089 /* Execute backend !!! */
1090 int ret = execv(cmd, argv);
1092 /* Code below: exec failure. Should not be happened! */
1093 DBG(">>>>>> OOPS 2!!!");
1095 /* g_strfreev(args_vector); *//* FIXME: causes error */
1098 perror("fail to exec");
1103 gboolean queue_job(void *data)
1105 pm_dbus_msg *item = NULL;
1109 char *backend_cmd = NULL;
1111 /* Pop a job from queue */
1112 for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
1113 if (__is_backend_busy(x))
1116 item = _pm_queue_pop(x);
1117 if (item && item->req_type != -1)
1122 /* all backend messages queue are empty or busy */
1123 if (x == num_of_backends)
1126 __set_backend_busy(x);
1127 __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
1130 _save_queue_status(item, "processing");
1131 DBG("saved queue status. Now try fork()");
1132 /*save pkg type and pkg name for future*/
1133 strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
1134 strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
1135 strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
1136 ptr->uid = item->uid;
1138 DBG("child forked [%d] for request type [%d]", ptr->pid, item->req_type);
1142 switch (item->req_type) {
1143 case COMM_REQ_TO_INSTALLER:
1144 DBG("before run _get_backend_cmd()");
1145 /*Check for efl-tpk app*/
1146 backend_cmd = _get_backend_cmd(item->pkg_type);
1147 if (backend_cmd == NULL)
1150 if (strcmp(item->pkg_type, "tpk") == 0) {
1151 ret = __is_efl_tpk_app(item->pkgid);
1155 backend_cmd = _get_backend_cmd("efltpk");
1159 DBG("Try to exec [%s][%s]", item->pkg_type, backend_cmd);
1160 fprintf(stdout, "Try to exec [%s][%s]\n", item->pkg_type, backend_cmd);
1162 char **args_vector = __generate_argv(item->args);
1163 args_vector[0] = backend_cmd;
1165 /* Execute backend !!! */
1166 __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
1169 case COMM_REQ_TO_ACTIVATOR:
1170 DBG("activator start");
1172 if (item->args[0] == '1') /* activate */
1174 else if (item->args[0] == '0') /* deactivate */
1177 DBG("error in args parameter:[%c]\n",
1182 DBG("activated val %d", val);
1187 GError *gerr = NULL;
1189 user_ctx* user_context = get_user_context(item->uid);
1191 DBG("Failed to getenv for the user : %d", item->uid);
1194 if(set_environement(user_context)){
1195 DBG("Failed to set env for the user : %d", item->uid);
1198 free_user_context(user_context);
1200 ret_parse = g_shell_parse_argv(item->args,
1201 &argcp, &argvp, &gerr);
1202 if (FALSE == ret_parse) {
1203 DBG("Failed to split args: %s", item->args);
1204 DBG("messsage: %s", gerr->message);
1208 if (!strcmp(argvp[1], "APP")) { /* in case of application */
1209 DBG("(De)activate APP");
1211 while ((opt = getopt(argcp, argvp, "l:")) != -1) {
1214 label = strdup(optarg);
1215 DBG("activated label %s", label);
1218 ERR("Incorrect argument %s\n", item->args);
1223 ret = pkgmgrinfo_appinfo_set_usr_state_enabled(item->pkgid, val, item->uid);
1224 if (ret != PMINFO_R_OK) {
1225 perror("fail to activate/deactivte package");
1230 ret = pkgmgrinfo_appinfo_set_usr_default_label(item->pkgid, label, item->uid);
1231 if (ret != PMINFO_R_OK) {
1232 perror("fail to activate/deactivte package");
1237 } else { /* in case of package */
1238 ERR("(De)activate PKG[pkgid=%s, val=%d]", item->pkgid, val);
1239 char *manifest = NULL;
1240 manifest = pkgmgr_parser_get_manifest_file(item->pkgid);
1241 if (manifest == NULL) {
1242 ERR("Failed to fetch package manifest file\n");
1245 ERR("manifest : %s\n", manifest);
1248 pkgmgrinfo_pkginfo_h handle;
1249 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid, &handle);
1251 ret = pkgmgr_parser_parse_usr_manifest_for_installation(manifest,item->uid, NULL);
1253 ERR("insert in db failed\n");
1256 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1259 ret = pkgmgrinfo_appinfo_set_usr_state_enabled(item->pkgid, val, item->uid);
1260 if (ret != PMINFO_R_OK) {
1261 perror("fail to activate/deactivte package");
1266 ret = pkgmgr_parser_parse_usr_manifest_for_uninstallation(manifest, item->uid, NULL);
1269 ERR("insert in db failed\n");
1274 case COMM_REQ_TO_MOVER:
1275 case COMM_REQ_TO_CLEARER:
1276 DBG("cleaner start");
1277 DBG("before run _get_backend_cmd()");
1278 backend_cmd = _get_backend_cmd(item->pkg_type);
1279 if (NULL == backend_cmd)
1282 DBG("Try to exec [%s][%s]", item->pkg_type, backend_cmd);
1283 fprintf(stdout, "Try to exec [%s][%s]\n", item->pkg_type, backend_cmd);
1285 char **args_vectors = __generate_argv(item->args);
1286 args_vectors[0] = backend_cmd;
1288 /* Execute backend !!! */
1289 __exec_with_arg_vector(backend_cmd, args_vectors, item->uid);
1292 case COMM_REQ_GET_SIZE:
1293 DBG("before run _get_backend_cmd()");
1294 __exec_with_arg_vector("usr/bin/pkg_getsize", __generate_argv(item->args), item->uid);
1296 case COMM_REQ_KILL_APP:
1297 case COMM_REQ_CHECK_APP:
1298 DBG("COMM_REQ_CHECK_APP start");
1299 pkgmgrinfo_pkginfo_h handle;
1300 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid, &handle);
1302 DBG("Failed to get handle\n");
1306 if (item->req_type == COMM_REQ_KILL_APP) {
1307 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMSVC_ALL_APP, __pkgcmd_app_cb, "kill", item->uid);
1309 DBG("pkgmgrinfo_appinfo_get_list() failed\n");
1310 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1313 } else if (item->req_type == COMM_REQ_CHECK_APP) {
1314 ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMSVC_ALL_APP, __pkgcmd_app_cb, "check", item->uid);
1316 DBG("pkgmgrinfo_appinfo_get_list() failed\n");
1317 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1321 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1325 _save_queue_status(item, "done");
1330 fprintf(stderr, "Fail to execute_fork()\n");
1333 default: /* parent */
1334 DBG("parent exit\n");
1335 _save_queue_status(item, "done");
1344 #define IS_WHITESPACE(CHAR) \
1345 ((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
1347 void _app_str_trim(char *input)
1349 char *trim_str = input;
1354 while (*input != 0) {
1355 if (!IS_WHITESPACE(*input)) {
1366 char *_get_backend_cmd(char *type)
1369 char buffer[1024] = { 0 };
1370 char *command = NULL;
1372 fp = fopen(PKG_CONF_PATH, "r");
1378 while (fgets(buffer, 1024, fp) != NULL) {
1379 if (buffer[0] == '#')
1382 _app_str_trim(buffer);
1384 if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
1385 DBG("buffer [%s]", buffer);
1386 path = path + strlen(PKG_BACKEND);
1387 DBG("path [%s]", path);
1390 (char *)malloc(sizeof(char) * strlen(path) +
1392 if (command == NULL) {
1397 size = strlen(path) + strlen(type) + 1;
1398 snprintf(command, size, "%s%s", path, type);
1399 command[strlen(path) + strlen(type)] = '\0';
1400 DBG("command [%s]", command);
1408 memset(buffer, 0x00, 1024);
1414 return NULL; /* cannot find proper command */
1417 int main(int argc, char *argv[])
1419 FILE *fp_status = NULL;
1420 char buf[32] = { 0, };
1422 char *backend_cmd = NULL;
1423 char *backend_name = NULL;
1426 DBG("server start");
1428 if (argv[1] && (strcmp(argv[1], "init") == 0)) {
1429 /* if current status is "processing",
1430 execute related backend with '-r' option */
1431 if (!(fp_status = fopen(STATUS_FILE, "r")))
1432 return 0; /*if file is not exist, terminated. */
1433 /* if processing <-- unintended termination */
1434 if (fgets(buf, 32, fp_status) &&
1435 strcmp(buf, "processing") == 0) {
1437 if (pid == 0) { /* child */
1438 if (fgets(buf, 32, fp_status))
1439 backend_cmd = _get_backend_cmd(buf);
1440 if (!backend_cmd) { /* if NULL, */
1442 " backend command");
1446 strrchr(backend_cmd, '/');
1448 execl(backend_cmd, backend_name, "-r",
1452 fprintf(fp_status, " ");
1456 } else if (pid < 0) { /* error */
1460 } else { /* parent */
1462 DBG("parent end\n");
1463 fprintf(fp_status, " ");
1470 r = _pm_queue_init();
1472 DBG("Queue Initialization Failed\n");
1476 r = __init_backend_info();
1478 DBG("backend info init failed");
1482 r = cynara_initialize(&p_cynara, NULL);
1483 if (r != CYNARA_API_SUCCESS) {
1484 ERR("cynara initialize failed with code=%d", r);
1488 #if !GLIB_CHECK_VERSION(2,35,0)
1491 mainloop = g_main_loop_new(NULL, FALSE);
1493 ERR("g_main_loop_new failed");
1497 DBG("Main loop is created.");
1499 PkgMgrObject *pkg_mgr;
1500 pkg_mgr = g_object_new(PKG_MGR_TYPE_OBJECT, NULL);
1501 pkg_mgr_set_request_callback(pkg_mgr, req_cb, NULL);
1502 DBG("pkg_mgr object is created, and request callback is registered.");
1504 g_main_loop_run(mainloop);
1506 DBG("Quit main loop.");
1508 __fini_backend_info();
1509 cynara_finish(p_cynara);
1511 DBG("package manager server terminated.");