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.
35 #include <pkgmgr_installer.h>
37 #include "rpm-installer.h"
38 #include "rpm-frontend.h"
39 #include "rpm-installer-type.h"
41 char *gpkgname = NULL;
42 extern char scrolllabel[256];
50 struct ri_backend_data_t {
57 typedef struct ri_backend_data_t ri_backend_data;
58 static int __ri_native_recovery(int lastbackstate);
59 static int __ri_uninstall_package(char *pkgid);
60 static int __ri_clear_private_data(char *pkgid);
61 static int __ri_move_package(char *pkgid, int move_type);
62 static inline int __ri_read_proc(const char *path, char *buf, int size);
63 static inline int __ri_find_pid_by_cmdline(const char *dname,
66 static bool __ri_is_another_instance_running(const char *exepath);
68 static int __ri_uninstall_package(char *pkgid)
72 return RPM_INSTALLER_ERR_WRONG_PARAM;
74 ret = _rpm_installer_package_uninstall(pkgid);
75 if (ret == RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED) {
76 _LOGE("[__ri_uninstall_package]%s "
77 "not installed\n", pkgid);
78 } else if (ret != 0) {
80 "[__ri_uninstall_package]%s uninstall failed(%d)\n",
84 "[__ri_uninstall_package]%s successfully uninstalled\n",
90 static int __ri_clear_private_data(char *pkgid)
93 return RPM_INSTALLER_ERR_WRONG_PARAM;
95 ret = _rpm_installer_clear_private_data(pkgid);
96 if (ret == RPM_INSTALLER_SUCCESS) {
98 "[__clear_private_data]%s clear data successful\n",
102 "[__clear_private_data]%s clear data failed(%d)\n",
108 static int __ri_move_package(char *pkgid, int move_type)
111 return RPM_INSTALLER_ERR_WRONG_PARAM;
117 gpkgname = strdup(pkgid);
119 _LOGE("Malloc failed!!");
120 return RPM_INSTALLER_ERR_INTERNAL;
122 ret = _rpm_move_pkg(pkgid, move_type);
123 if (ret == RPM_INSTALLER_SUCCESS) {
125 "[__ri_move_package]%s move successful\n",
129 "[__ri_move_package]%s move failed(%d)\n",
135 static inline int __ri_read_proc(const char *path, char *buf, int size)
140 if (buf == NULL || path == NULL)
143 fd = open(path, O_RDONLY);
147 ret = read(fd, buf, size - 1);
159 static inline int __ri_find_pid_by_cmdline(const char *dname,
164 if (strncmp(cmdline, priv, strlen(RPM)) == 0) {
166 if (pid != getpgid(pid))
175 static bool __ri_is_another_instance_running(const char *exepath)
178 struct dirent *dentry;
181 char buf[256] = { 0, };
182 char buf1[256] = { 0, };
183 dp = opendir("/proc");
187 while ((dentry = readdir(dp)) != NULL) {
188 if (!isdigit(dentry->d_name[0]))
190 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
191 ret = __ri_read_proc(buf, buf1, sizeof(buf));
194 pid = __ri_find_pid_by_cmdline(dentry->d_name, buf1, exepath);
206 static int __ri_native_recovery(int lastbackstate)
213 _LOGD("Rpm Installer Recovery Entry \n");
215 /* which package it was installing and what was state at that time */
216 _ri_get_last_input_info(&pn, &lreq, &opt);
218 switch (lastbackstate) {
219 case REQUEST_ACCEPTED:
220 case GOT_PACKAGE_INFO_SUCCESSFULLY:
222 * restart the last operation
225 "Rpm Installer Recovery started. state=%d \n", lastbackstate);
229 _rpm_installer_package_install(pn, true, "--force", NULL);
235 err = _rpm_installer_package_uninstall(pn);
239 case EFLWGT_INSTALL_CMD:
240 err = _rpm_installer_package_uninstall(pn);
250 "Recovery of command(%d) is to be implemented\n", lreq);
255 " Rpm Installer Recovery Ended \n");
257 case REQUEST_COMPLETED:
259 " Rpm Installer Recovery. Nothing To Be Done\n");
260 _ri_set_backend_state_info(REQUEST_COMPLETED);
263 case REQUEST_PENDING:
265 "Rpm Installer Recovery started. state=%d\n", lastbackstate);
266 /*Only package downgradation can be the case*/
267 err = _rpm_installer_package_install(pn, true, "--force", NULL);
268 if (err != RPM_INSTALLER_SUCCESS &&
269 err != RPM_INSTALLER_ERR_NEED_USER_CONFIRMATION) {
273 " Rpm Installer Recovery ended \n");
274 _ri_set_backend_state_info(REQUEST_COMPLETED);
283 " Rpm Installer Recovery Default state \n");
291 _LOGE("Error in Recovery error number = (%d)\n",
298 static int __ri_check_root_path(const char *pkgid)
300 char dirpath[BUF_SIZE] = {'\0'};
301 struct stat stFileInfo;
303 snprintf(dirpath, BUF_SIZE, "/usr/apps/%s", pkgid);
305 (void)stat(dirpath, &stFileInfo);
307 if (S_ISDIR(stFileInfo.st_mode)) {
308 return 0; //it menas "/usr/apps/pkgid"
310 return 1; //it menas "/opt/usr/apps/pkgid"
313 void __ri_make_directory(const char *pkgid)
315 char usr_pkg[BUF_SIZE] = {'\0'};
316 char opt_pkg[BUF_SIZE] = {'\0'};
319 snprintf(usr_pkg, BUF_SIZE, "%s/%s/%s", USR_APPS, pkgid, AUTHOR_SIGNATURE_XML);
320 snprintf(opt_pkg, BUF_SIZE, "%s/%s/%s", OPT_USR_APPS, pkgid, AUTHOR_SIGNATURE_XML);
322 // check author signature
323 if ((access(opt_pkg, R_OK) == 0) || (access(usr_pkg, R_OK) == 0)) {
324 _LOGE("pkgid[%s] has author-signature",pkgid);
327 memset(opt_pkg, '\0', BUF_SIZE);
328 snprintf(opt_pkg, BUF_SIZE, "%s/%s", OPT_USR_APPS, pkgid);
329 if (access(opt_pkg, R_OK) != 0) {
330 _LOGE("dont have [%s]\n",opt_pkg);
331 ret = mkdir(opt_pkg, DIRECTORY_PERMISSION_755);
333 _LOGE("directory making is failed.\n");
335 _LOGE("directory[%s] is created", opt_pkg);
340 memset(opt_pkg, '\0', BUF_SIZE);
341 snprintf(opt_pkg, BUF_SIZE, "%s/%s/shared", OPT_USR_APPS, pkgid);
342 if (access(opt_pkg, R_OK) != 0) {
343 _LOGE("dont have [%s]\n",opt_pkg);
344 ret = mkdir(opt_pkg, DIRECTORY_PERMISSION_755);
346 _LOGE("directory making is failed.\n");
348 _LOGE("directory[%s] is created", opt_pkg);
353 memset(opt_pkg, '\0', BUF_SIZE);
354 snprintf(opt_pkg, BUF_SIZE, "%s/%s/shared/data", OPT_USR_APPS, pkgid);
355 if (access(opt_pkg, R_OK) != 0) {
356 _LOGE("dont have [%s]\n",opt_pkg);
357 ret = mkdir(opt_pkg, DIRECTORY_PERMISSION_755);
359 _LOGE("directory making is failed.\n");
361 _LOGE("directory[%s] is created", opt_pkg);
366 memset(opt_pkg, '\0', BUF_SIZE);
367 snprintf(opt_pkg, BUF_SIZE, "%s/%s/shared/trusted", OPT_USR_APPS, pkgid);
368 if (access(opt_pkg, R_OK) != 0) {
369 _LOGE("dont have [%s],\n",opt_pkg);
370 ret = mkdir(opt_pkg, DIRECTORY_PERMISSION_755);
372 _LOGE("directory making is failed.\n");
374 _LOGE("directory[%s] is created", opt_pkg);
381 static int __ri_process_smack(char *keyid, char *pkgid)
385 /*apply smack for ug*/
386 if(strcmp(keyid,"ug-smack")==0) {
387 _LOGD("only apply smack for ug\n");
388 const char *perm[] = {"http://tizen.org/privilege/appsetting", NULL};
389 _ri_apply_smack(pkgid,__ri_check_root_path(pkgid));
390 _ri_privilege_enable_permissions(pkgid, 1, perm, 1);
391 /*apply smack for rpm package*/
392 } else if (strcmp(keyid,"rpm-smack")==0) {
393 _LOGD("apply smack for rpm");
394 __ri_make_directory(pkgid);
395 _ri_apply_smack(pkgid,__ri_check_root_path(pkgid));
397 /*soft-reset for rpm package*/
398 } else if (strcmp(keyid,"soft-reset")==0) {
399 _LOGD("soft-reset\n");
400 _ri_soft_reset(pkgid);
402 /*register xml to db, call pkgmgr parser*/
403 } else if (strcmp(keyid,"core-xml")==0) {
404 _LOGD("install corexml");
405 ret = _rpm_installer_corexml_install(pkgid);
407 _LOGE("corexml_install failed with err(%d)\n", ret);
409 _LOGD("manifest is installed successfully");
411 /*apply privilege for rpm package*/
412 } else if (strcmp(keyid,"rpm-perm")==0) {
413 _LOGD("apply privileges for rpm");
414 ret = _ri_apply_privilege(pkgid, 0);
416 _LOGE("apply privileges failed with err(%d)", ret);
418 _LOGD("apply privileges success");
421 } else if (strcmp(keyid,"csc-xml")==0) {
422 _LOGD("csc xml for rpm\n");
423 ret = _rpm_process_cscxml(pkgid);
425 _LOGE("install csc xml failed with err(%d)\n", ret);
427 _LOGD("install csc xml success\n");
430 /*check csc coretpk*/
431 } else if (strcmp(keyid,"csc-core")==0) {
432 _LOGD("csc for coretpk\n");
433 ret = _rpm_process_csc_coretpk(pkgid);
435 _LOGE("install coretpk csc failed with err(%d)\n", ret);
437 _LOGD("install coretpk csc success\n");
441 } else if (strcmp(keyid,"rpm-fota")==0) {
442 _LOGD("fota process for rpm\n");
443 ret = _rpm_process_fota(pkgid);
445 _LOGE("fota process failed with err(%d)\n", ret);
447 _LOGD("fota process success\n");
450 } else if (strcmp(keyid,"rpm-rw-fota")==0) {
451 _LOGD("rw fota process for rpm\n");
452 ret = _rpm_process_fota_for_rw(pkgid);
454 _LOGE("rw fota process failed with err(%d)\n", ret);
456 _LOGD("rw fota process success\n");
459 _LOGE("smack cmd error\n");
466 int _rpm_backend_interface(char *keyid, char *pkgid, char *reqcommand, char *clientid)
469 ri_backend_data data = { 0 };
472 if (reqcommand == NULL) {
473 _LOGE("reqcommand is NULL\n");
474 return RPM_INSTALLER_ERR_WRONG_PARAM;
476 if (keyid == NULL || pkgid == NULL) {
477 if (strncmp(reqcommand, "recover", strlen("recover"))) {
478 _LOGE(" Either keyid/pkgid is NULL\n");
479 return RPM_INSTALLER_ERR_WRONG_PARAM;
481 _LOGE(" Either keyid/pkgid is NULL\n");
482 return RPM_INSTALLER_ERR_WRONG_PARAM;
485 if (strncmp(reqcommand, "install", strlen("install")) == 0) {
486 data.req_cmd = INSTALL_CMD;
487 data.cmd_string = strdup("install");
488 if (data.cmd_string == NULL) {
490 "strdup failed due to insufficient memory\n");
491 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
493 } else if (strncmp(reqcommand, "remove", strlen("remove")) == 0) {
494 data.req_cmd = DELETE_CMD;
495 data.cmd_string = strdup("uninstall");
496 if (data.cmd_string == NULL) {
498 "strdup failed due to insufficient memory\n");
499 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
501 } else if (strncmp(reqcommand, "recover", strlen("recover")) == 0) {
502 data.req_cmd = RECOVER_CMD;
503 data.cmd_string = strdup("recover");
504 if (data.cmd_string == NULL) {
506 "strdup failed due to insufficient memory\n");
507 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
509 } else if (strncmp(reqcommand, "cleardata", strlen("cleardata")) == 0) {
510 data.req_cmd = CLEARDATA_CMD;
511 data.cmd_string = strdup("cleardata");
512 if (data.cmd_string == NULL) {
514 "strdup failed due to insufficient memory\n");
515 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
517 } else if (strncmp(reqcommand, "move", strlen("move")) == 0) {
518 data.req_cmd = MOVE_CMD;
519 data.cmd_string = strdup("move");
520 if (data.cmd_string == NULL) {
522 "strdup failed due to insufficient memory\n");
523 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
525 } else if (strncmp(reqcommand, "smack", strlen("smack")) == 0) {
526 return __ri_process_smack(keyid, pkgid);
527 } else if (strncmp(reqcommand, "eflwgt-install", strlen("eflwgt-install")) == 0) {
528 data.req_cmd = EFLWGT_INSTALL_CMD;
529 data.cmd_string = strdup("eflwgt-install");
530 if (data.cmd_string == NULL) {
532 "strdup failed due to insufficient memory\n");
533 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
535 } else if (strncmp(reqcommand, "rpm-enable", strlen("rpm-enable")) == 0) {
536 if (strstr(pkgid, ":") == NULL)
537 ret = _rpm_process_enable(pkgid);
539 ret = _rpm_process_enabled_list(pkgid);
541 } else if (strncmp(reqcommand, "rpm-disable", strlen("rpm-disable")) == 0) {
542 if (strstr(pkgid, ":") == NULL)
543 ret = _rpm_process_disable(pkgid);
545 ret = _rpm_process_disabled_list(pkgid);
548 _LOGD("wrong input parameter\n");
549 _LOGD("%d\n", RPM_INSTALLER_ERR_WRONG_PARAM);
550 return RPM_INSTALLER_ERR_WRONG_PARAM;
554 backendstate = _ri_get_backend_state();
556 rc = rpmReadConfigFiles(NULL, NULL);
557 if (rc == RPMRC_OK) {
558 _LOGD("Successfully read rpm configuration\n");
560 _LOGE("Unable to read RPM configuration.\n");
561 if (data.cmd_string) {
562 free(data.cmd_string);
563 data.cmd_string = NULL;
565 return RPM_INSTALLER_ERR_INTERNAL;
568 if (RECOVER_CMD == data.req_cmd) {
569 if (0 == backendstate) {
572 /* check the current state of backend */
573 lastbackstate = _ri_get_backend_state_info();
575 if (REQUEST_COMPLETED == lastbackstate) {
577 " Rpm Installer recovery is in REQUEST_COMPLETED \n");
578 snprintf(scrolllabel, sizeof(scrolllabel),
579 "No Recovery Needed");
581 ret = __ri_native_recovery(lastbackstate);
583 snprintf(scrolllabel, sizeof(scrolllabel),
586 snprintf(scrolllabel, sizeof(scrolllabel),
589 /* set the backend state as completed */
590 _ri_set_backend_state(1);
592 /* nothing to recover */
594 " Rpm Installer recovery Nothing to be done\n");
596 snprintf(scrolllabel, sizeof(scrolllabel),
597 "No Recovery Needed");
600 if (data.cmd_string) {
601 free(data.cmd_string);
602 data.cmd_string = NULL;
607 if (backendstate == 0) {
611 * Another Instance may be running
612 * or something went wrong in last execution
615 if (__ri_is_another_instance_running(RPM)) {
617 _ri_broadcast_status_notification
618 (data.pkgid, "rpm", "error",
619 "Another Instance Running");
620 _ri_stat_cb(data.pkgid, "error",
621 "Another Instance Running");
622 _ri_broadcast_status_notification
623 (data.pkgid, "rpm", "end", "fail");
624 _ri_stat_cb(data.pkgid, "end",
627 _ri_broadcast_status_notification
628 ("unknown", "unknown", "error",
629 "Another Instance Running");
630 _ri_stat_cb("unknown", "error",
631 "Another Instance Running");
632 _ri_broadcast_status_notification
633 ("unknown", "unknown", "end", "fail");
634 _ri_stat_cb("unknown", "end", "fail");
638 "Another Instance is running \n");
639 ret = RPM_INSTALLER_ERR_RESOURCE_BUSY;
640 if (data.cmd_string) {
641 free(data.cmd_string);
642 data.cmd_string = NULL;
648 /* check the current state of backend */
649 lastbackstate = _ri_get_backend_state_info();
651 /* Publish Notification that backend has started */
652 // _ri_broadcast_status_notification(data.pkgid, "rpm", "start", data.cmd_string);
653 // _ri_broadcast_status_notification(data.pkgid, "rpm", "command", data.cmd_string);
655 if (REQUEST_COMPLETED == lastbackstate) {
657 " Rpm Installer recovery"
658 " is in REQUEST_COMPLETED \n");
661 ret = __ri_native_recovery(lastbackstate);
664 "recovery of last request failed\n");
667 "recovery of last request success\n");
670 /* set the backend state as completed */
671 _ri_set_backend_state(1);
675 /* set the backend state as started for the current request*/
676 _ri_set_backend_state(0);
679 gpkgname = strdup(data.pkgid);
681 /* Publish Notification that backend has started */
683 _ri_broadcast_status_notification(data.pkgid, "rpm", "start",
686 _ri_broadcast_status_notification("unknown", "start",
690 _ri_set_backend_state_info(REQUEST_ACCEPTED);
692 /* Set the input request info */
693 if(data.pkgid == NULL)
694 return RPM_INSTALLER_ERR_PKG_NOT_FOUND;
695 _ri_save_last_input_info(data.pkgid, data.req_cmd,
696 data.force_overwrite);
698 switch (data.req_cmd) {
701 _LOGD("[%s] --install %s\n",
702 "backend", data.pkgid);
704 _ri_broadcast_status_notification(data.pkgid, "rpm",
705 "command", "Install");
707 if (data.force_overwrite == FORCE_OVERWITE) {
709 "[%s] --install %s --force-overwrite\n",
710 "backend", data.pkgid);
712 _rpm_installer_package_install
713 (data.pkgid, true, "--force", clientid);
715 if(data.pkgid == NULL) {
716 _LOGE("pkgid is null");
719 _LOGD("[%s] --install %s\n",
720 "backend", data.pkgid);
722 _rpm_installer_package_install
723 (data.pkgid, false, NULL, clientid);
729 _LOGD("[%s] uninstall %s\n",
730 "backend", data.pkgid);
732 _ri_broadcast_status_notification(data.pkgid, "rpm",
733 "command", "Remove");
735 ret = __ri_uninstall_package(data.pkgid);
737 _LOGD("remove fail\n");
739 _LOGD("remove success\n");
745 _LOGD("[%s] clear data %s\n",
746 "backend", data.pkgid);
748 _ri_broadcast_status_notification(data.pkgid, "rpm",
751 ret = __ri_clear_private_data(data.pkgid);
754 _ri_error_no_to_string(ret, &errstr);
755 _ri_broadcast_status_notification(data.pkgid, "rpm",
758 _ri_stat_cb(data.pkgid, "error", errstr);
759 _ri_broadcast_status_notification(data.pkgid, "rpm",
762 _ri_stat_cb(data.pkgid, "end", "fail");
764 "clear data failed with err(%d) (%s)\n",
767 _LOGD("clear data success\n");
768 _ri_broadcast_status_notification(data.pkgid, "rpm",
770 _ri_stat_cb(data.pkgid, "end", "ok");
776 _LOGD("[%s] move %s\n",
777 "backend", data.pkgid);
779 _ri_broadcast_status_notification(data.pkgid, "rpm",
782 ret = __ri_move_package(data.pkgid, move_type);
785 _ri_error_no_to_string(ret, &errstr);
786 _ri_broadcast_status_notification(data.pkgid, "rpm",
789 _ri_stat_cb(data.pkgid, "error", errstr);
790 _ri_broadcast_status_notification(data.pkgid, "rpm",
793 _ri_stat_cb(data.pkgid, "end", "fail");
795 "move failed with err(%d) (%s)\n",
798 _LOGD("move success\n");
799 _ri_broadcast_status_notification(data.pkgid, "rpm",
801 _ri_stat_cb(data.pkgid, "end", "ok");
805 case EFLWGT_INSTALL_CMD:
808 _LOGD("[%s] eflwgt-install %s\n",
809 "backend", data.pkgid);
811 _ri_broadcast_status_notification(data.pkgid, "rpm",
812 "command", "eflwgt-install");
814 ret = _rpm_installer_package_install_with_dbpath(data.pkgid, clientid);
817 _ri_error_no_to_string(ret, &errstr);
818 _ri_broadcast_status_notification(data.pkgid, "rpm",
821 _ri_stat_cb(data.pkgid, "error", errstr);
823 _ri_broadcast_status_notification(data.pkgid, "rpm",
826 _ri_stat_cb(data.pkgid, "end", "fail");
827 _LOGE("eflwgt-install failed with err(%d) (%s)\n",
830 _LOGD("eflwgt-install success\n");
831 _ri_broadcast_status_notification(data.pkgid, "rpm",
833 _ri_stat_cb(data.pkgid, "end", "ok");
835 _ri_remove_wgt_unzip_dir();
841 _ri_broadcast_status_notification("unknown", "unknown",
844 _ri_broadcast_status_notification("unknown", "unknown",
847 _ri_stat_cb("unknown", "error", "not supported");
848 _ri_broadcast_status_notification("unknown", "unknown",
850 _ri_stat_cb("unknown", "end", "fail");
851 _LOGE("unknown command \n");
852 ret = RPM_INSTALLER_ERR_WRONG_PARAM;
861 if (data.cmd_string) {
862 free(data.cmd_string);
863 data.cmd_string = NULL;
866 if (_ri_get_backend_state_info() != REQUEST_PENDING) {
867 _ri_set_backend_state_info(REQUEST_COMPLETED);
868 /* set the backend state as completed */
869 _ri_set_backend_state(1);