--- /dev/null
+Jayoun Lee <airjany@samsung.com>
+Sewook Park <sewook7.park@samsung.com>
+Jaeho Lee <jaeho81.lee@samsung.com>
+Shobhit Srivastava <shobhit.s@samsung.com>
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+SET(CMAKE_SKIP_BUILD_RPATH true)
+
+PROJECT(pkgmgr-server C)
+SET(VERSION_MAJOR 0)
+SET(VERSION ${VERSION_MAJOR}.1.68)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR ${LIB_INSTALL_DIR})
+SET(INCLUDEDIR "\${prefix}/include")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -g -Wall")
+
+INCLUDE_DIRECTORIES(include)
+INCLUDE(FindPkgConfig)
+
+SET(PKGMGR_SERVER "pkgmgr-server")
+SET(SRCS src/pkgmgr-server.c src/request.c src/pm-queue.c)
+
+pkg_check_modules(SERVER_DEPS REQUIRED
+ gio-2.0
+ dlog
+ pkgmgr-parser
+ pkgmgr-info
+ libtzplatform-config
+ pkgmgr)
+FOREACH(SERVER_FLAGS ${SERVER_DEPS_CFLAGS})
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SERVER_FLAGS}")
+ENDFOREACH(SERVER_FLAGS)
+
+ADD_EXECUTABLE(${PKGMGR_SERVER} ${SRCS})
+TARGET_LINK_LIBRARIES(${PKGMGR_SERVER} pkgmgr_installer)
+TARGET_LINK_LIBRARIES(${PKGMGR_SERVER} ${SERVER_DEPS_LDFLAGS})
+
+CONFIGURE_FILE(org.tizen.pkgmgr.service.in org.tizen.pkgmgr.service @ONLY)
+CONFIGURE_FILE(org.tizen.pkgmgr.conf.in org.tizen.pkgmgr.conf @ONLY)
+
+INSTALL(TARGETS ${PKGMGR_SERVER} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/queue_status DESTINATION ${SYSCONF_INSTALL_DIR}/package-manager/server/)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.tizen.pkgmgr.service DESTINATION ${PREFIX}/share/dbus-1/system-services/)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.tizen.pkgmgr.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d/)
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
--- /dev/null
+/*
+ * slp-pkgmgr
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _PKGMGR_SERVER_H_
+#define _PKGMGR_SERVER_H_
+
+#include <glib.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif /* LOG_TAG */
+#define LOG_TAG "PKGMGR_SERVER"
+#include "package-manager-debug.h"
+
+#define CONF_FILE "/etc/package-manager/server/.config"
+#define DESKTOP_FILE_DIRS "/usr/share/install-info/desktop.conf"
+
+#define PKG_BACKEND "backend:"
+#define PKG_CONF_PATH "/etc/package-manager/pkg_path.conf"
+
+#define MAX_REQ_ID_LEN 256
+#define MAX_PKG_TYPE_LEN 128
+#define MAX_PKG_NAME_LEN 256
+#define MAX_PKG_ARGS_LEN 4096
+#define DESKTOP_FILE_DIRS_NUM 1024
+
+enum request_type {
+ PKGMGR_REQUEST_TYPE_INSTALL,
+ PKGMGR_REQUEST_TYPE_REINSTALL,
+ PKGMGR_REQUEST_TYPE_UNINSTALL,
+ PKGMGR_REQUEST_TYPE_MOVE,
+ PKGMGR_REQUEST_TYPE_ENABLE,
+ PKGMGR_REQUEST_TYPE_DISABLE,
+ PKGMGR_REQUEST_TYPE_GETSIZE,
+ PKGMGR_REQUEST_TYPE_CLEARDATA,
+ PKGMGR_REQUEST_TYPE_CLEARCACHE,
+ PKGMGR_REQUEST_TYPE_KILL,
+ PKGMGR_REQUEST_TYPE_CHECK,
+};
+
+typedef struct {
+ char req_id[MAX_REQ_ID_LEN];
+ int req_type;
+ uid_t uid;
+ char pkg_type[MAX_PKG_TYPE_LEN];
+ char pkgid[MAX_PKG_NAME_LEN];
+ char args[MAX_PKG_ARGS_LEN];
+} pm_dbus_msg;
+
+typedef struct backend_info_t {
+ int pid;
+ uid_t uid;
+ char pkgtype[MAX_PKG_TYPE_LEN];
+ char pkgid[MAX_PKG_NAME_LEN];
+ char args[MAX_PKG_ARGS_LEN];
+} backend_info;
+
+char *_get_backend_cmd(char *type);
+
+gboolean queue_job(void *data);
+int __init_request_handler(void);
+void __fini_request_handler(void);
+
+#endif/* _PKGMGR_SERVER_H_ */
--- /dev/null
+/*
+ * slp-pkgmgr
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+
+
+
+#ifndef _PM_QUEUE_H_
+#define _PM_QUEUE_H_
+
+#include "pkgmgr-server.h"
+
+#define STATUS_FILE "/etc/package-manager/server/queue_status"
+/* #define STATUS_FILE "./queue_status" */
+
+typedef struct _pm_queue_data {
+ pm_dbus_msg *msg;
+ struct _pm_queue_data *next;
+} pm_queue_data;
+
+typedef struct queue_info_map_t {
+ char pkgtype[MAX_PKG_TYPE_LEN];
+ char backend[MAX_PKG_NAME_LEN];
+ int queue_slot;
+ pm_queue_data *head;
+} queue_info_map;
+
+#define MAX_QUEUE_NUM 128
+
+int _pm_queue_init(void);
+int _pm_queue_push(uid_t uid, const char *req_id, int req_type,
+ const char *pkg_type, const char *pkgid, const char *argv);
+/*position specifies the queue from which to pop request*/
+pm_dbus_msg *_pm_queue_pop(int position);
+void _pm_queue_final();
+void _pm_queue_delete(pm_dbus_msg *item);
+pm_queue_data *_add_node();
+void _save_queue_status(pm_dbus_msg *item, char *status);
+void _print_queue(int position);
+
+#endif /* _PM_QUEUE_H_ */
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<busconfig>
+ <policy user="root">
+ <allow own="org.tizen.pkgmgr"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.tizen.pkgmgr"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="install" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="reinstall" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="uninstall" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="move" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="activate" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="deactivate" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="getsize" privilege="http://tizen.org/privilege/packagemanager.info"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="clearcache" privilege="http://tizen.org/privilege/packagemanager.clearcache"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="kill" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+ <check send_destination="org.tizen.pkgmgr" send_interface="org.tizen.pkgmgr" send_member="check" privilege="http://tizen.org/privilege/packagemanager.info"/>
+ </policy>
+</busconfig>
--- /dev/null
+[D-BUS Service]
+User=root
+Name=org.tizen.pkgmgr
+Exec=@PREFIX@/bin/pkgmgr-server
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+Name: pkgmgr-server
+Summary: Packager Manager server package
+Version: 0.3.37
+Release: 1
+Group: Application Framework/Package Management
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1001: %{name}.manifest
+BuildRequires: cmake
+BuildRequires: unzip
+BuildRequires: gettext-tools
+BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(iniparser)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(security-manager)
+BuildRequires: pkgconfig(xdgmime)
+BuildRequires: pkgconfig(db-util)
+BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(pkgmgr)
+BuildRequires: pkgmgr-info-parser-devel
+BuildRequires: pkgmgr-info-parser
+BuildRequires: fdupes
+
+%description
+Packager Manager server package for packaging
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+%cmake .
+
+%__make %{?_smp_mflags}
+
+%install
+%make_install
+
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+mkdir -p %{buildroot}%{_sysconfdir}/package-manager/server
+
+%fdupes %{buildroot}
+
+%post
+/sbin/ldconfig
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_datadir}/dbus-1/system-services/org.tizen.pkgmgr.service
+%config %{_sysconfdir}/dbus-1/system.d/org.tizen.pkgmgr.conf
+%{_bindir}/pkgmgr-server
+%{_sysconfdir}/package-manager/server
+%exclude %{_sysconfdir}/package-manager/server/queue_status
+/usr/share/license/%{name}
--- /dev/null
+This file is for creating required directory.
--- /dev/null
+/*
+ * slp-pkgmgr
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <pkgmgr-info.h>
+#include <pkgmgr/pkgmgr_parser.h>
+#include <tzplatform_config.h>
+
+#include "pkgmgr_installer.h"
+#include "pkgmgr-server.h"
+#include "pm-queue.h"
+#include "comm_config.h"
+#include "package-manager.h"
+
+#define BUFMAX 128
+#define NO_MATCHING_FILE 11
+
+#define OWNER_ROOT 0
+#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+
+typedef struct {
+ char **env;
+ uid_t uid;
+ gid_t gid;
+} user_ctx;
+
+
+/*
+8 bit value to represent maximum 8 backends.
+Each bit position corresponds to a queue slot which
+is dynamically determined.
+*/
+char backend_busy = 0;
+extern int num_of_backends;
+
+struct signal_info_t {
+ pid_t pid;
+ int status;
+};
+
+static int pipe_sig[2];
+static GIOChannel *pipe_io;
+static guint pipe_wid;
+
+backend_info *begin;
+extern queue_info_map *start;
+extern int entries;
+
+GMainLoop *mainloop = NULL;
+
+
+/* operation_type */
+typedef enum {
+ OPERATION_INSTALL = 0,
+ OPERATION_UNINSTALL,
+ OPERATION_ACTIVATE,
+ OPERATION_REINSTALL,
+ OPERATION_MAX
+} OPERATION_TYPE;
+
+static int __check_backend_status_for_exit(void);
+static int __check_queue_status_for_exit(void);
+static int __is_backend_busy(int position);
+static void __set_backend_busy(int position);
+static void __set_backend_free(int position);
+static void sighandler(int signo);
+
+gboolean exit_server(void *data);
+
+/* To check whether a particular backend is free/busy*/
+static int __is_backend_busy(int position)
+{
+ return backend_busy & 1<<position;
+}
+/*To set a particular backend as busy*/
+static void __set_backend_busy(int position)
+{
+ backend_busy = backend_busy | 1<<position;
+}
+/*To set a particular backend as free */
+static void __set_backend_free(int position)
+{
+ backend_busy = backend_busy & ~(1<<position);
+}
+
+static int __is_global(uid_t uid)
+{
+ return (uid == OWNER_ROOT || uid == GLOBAL_USER) ? 1 : 0;
+}
+
+static const char *__get_recovery_file_path(uid_t uid)
+{
+ const char *path;
+
+ if (!__is_global(uid))
+ tzplatform_set_user(uid);
+
+ path = tzplatform_getenv(__is_global(uid)
+ ? TZ_SYS_RW_PACKAGES : TZ_USER_PACKAGES);
+
+ tzplatform_reset_user();
+
+ return path;
+}
+
+static void __set_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
+{
+ char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
+ char buffer[MAX_PKG_NAME_LEN] = { 0 };
+ char *pkgid_tmp = NULL;
+ FILE *rev_file = NULL;
+
+ if (pkgid == NULL) {
+ DBG("pkgid is null\n");
+ return;
+ }
+
+ /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
+ if (strstr(pkgid, "/")) {
+ pkgid_tmp = strrchr(pkgid, '/') + 1;
+ if (pkgid_tmp == NULL) {
+ DBG("pkgid_tmp[%s] is null\n", pkgid);
+ return;
+ }
+ snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
+ } else {
+ snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
+ }
+
+ rev_file = fopen(recovery_file, "w");
+ if (rev_file== NULL) {
+ DBG("rev_file[%s] is null\n", recovery_file);
+ return;
+ }
+
+ snprintf(buffer, MAX_PKG_NAME_LEN, "pkgid : %s\n", pkgid);
+ fwrite(buffer, sizeof(char), strlen(buffer), rev_file);
+
+ fclose(rev_file);
+}
+
+static void __unset_recovery_mode(uid_t uid, char *pkgid, char *pkg_type)
+{
+ int ret = -1;
+ char recovery_file[MAX_PKG_NAME_LEN] = { 0, };
+ char *pkgid_tmp = NULL;
+
+ if (pkgid == NULL) {
+ DBG("pkgid is null\n");
+ return;
+ }
+
+ /*if pkgid has a "/"charactor, that is a path name for installation, then extract pkgid from absolute path*/
+ if (strstr(pkgid, "/")) {
+ pkgid_tmp = strrchr(pkgid, '/') + 1;
+ if (pkgid_tmp == NULL) {
+ DBG("pkgid_tmp[%s] is null\n", pkgid);
+ return;
+ }
+ snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid_tmp);
+ } else {
+ snprintf(recovery_file, sizeof(recovery_file), "%s/%s", __get_recovery_file_path(uid), pkgid);
+ }
+
+ ret = remove(recovery_file);
+ if (ret < 0)
+ DBG("remove recovery_file[%s] fail\n", recovery_file);
+}
+
+static void send_fail_signal(char *pname, char *ptype, char *args)
+{
+ DBG("send_fail_signal start\n");
+ gboolean ret_parse;
+ gint argcp;
+ gchar **argvp;
+ GError *gerr = NULL;
+ pkgmgr_installer *pi;
+ pi = pkgmgr_installer_new();
+ if (!pi) {
+ DBG("Failure in creating the pkgmgr_installer object");
+ return;
+ }
+ ret_parse = g_shell_parse_argv(args,
+ &argcp, &argvp, &gerr);
+ if (FALSE == ret_parse) {
+ DBG("Failed to split args: %s", args);
+ DBG("messsage: %s", gerr->message);
+ pkgmgr_installer_free(pi);
+ return;
+ }
+
+ pkgmgr_installer_receive_request(pi, argcp, argvp);
+ pkgmgr_installer_send_signal(pi, ptype, pname, "end", "fail");
+ pkgmgr_installer_free(pi);
+ return;
+}
+
+static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data)
+{
+ int x;
+ GError *err = NULL;
+ GIOStatus s;
+ gsize len;
+ struct signal_info_t info;
+ backend_info *ptr = begin;
+
+ s = g_io_channel_read_chars(io, (gchar *)&info, sizeof(struct signal_info_t), &len, &err);
+ if (s != G_IO_STATUS_NORMAL) {
+ ERR("Signal pipe read failed: %s", err->message);
+ g_error_free(err);
+ return TRUE;
+ }
+
+ for (x = 0; x < num_of_backends; x++, ptr++) {
+ if (ptr && ptr->pid == info.pid)
+ break;
+ }
+
+ if (x == num_of_backends) {
+ ERR("Unknown child exit");
+ return -1;
+ }
+
+ __set_backend_free(x);
+ __unset_recovery_mode(ptr->uid, ptr->pkgid, ptr->pkgtype);
+ if (WIFSIGNALED(info.status) || WEXITSTATUS(info.status)) {
+ send_fail_signal(ptr->pkgid, ptr->pkgtype, ptr->args);
+ DBG("backend[%s] exit with error", ptr->pkgtype);
+ } else {
+ DBG("backend[%s] exit", ptr->pkgtype);
+ }
+
+ g_idle_add(queue_job, NULL);
+
+ return TRUE;
+}
+
+static int __init_backend_info(void)
+{
+ backend_info *ptr;
+
+ /*Allocate memory for holding pid, pkgtype and pkgid*/
+ ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info));
+ if (ptr == NULL) {
+ DBG("Malloc Failed\n");
+ return -1;
+ }
+ begin = ptr;
+
+ if (pipe(pipe_sig)) {
+ ERR("create pipe failed");
+ return -1;
+ }
+
+ pipe_io = g_io_channel_unix_new(pipe_sig[0]);
+ g_io_channel_set_encoding(pipe_io, NULL, NULL);
+ g_io_channel_set_buffered(pipe_io, FALSE);
+ pipe_wid = g_io_add_watch(pipe_io, G_IO_IN, pipe_io_handler, NULL);
+
+ return 0;
+}
+
+static void __fini_backend_info(void)
+{
+ g_source_remove(pipe_wid);
+ g_io_channel_unref(pipe_io);
+ close(pipe_sig[0]);
+ close(pipe_sig[1]);
+
+ /*Free backend info */
+ free(begin);
+}
+
+static void sighandler(int signo)
+{
+ struct signal_info_t info;
+
+ info.pid = waitpid(-1, &info.status, WNOHANG);
+ if (write(pipe_sig[1], &info, sizeof(struct signal_info_t)) < 0)
+ ERR("failed to write result: %s", strerror(errno));
+}
+
+static int __register_signal_handler(void)
+{
+ static int sig_reg = 0;
+ struct sigaction act;
+
+ if (sig_reg)
+ return 0;
+
+ act.sa_handler = sighandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &act, NULL) < 0) {
+ ERR("signal: SIGCHLD failed\n");
+ return -1;
+ }
+
+ g_timeout_add_seconds(2, exit_server, NULL);
+
+ sig_reg = 1;
+ return 0;
+}
+
+static int __check_backend_status_for_exit(void)
+{
+ int i = 0;
+ for(i = 0; i < num_of_backends; i++)
+ {
+ if (!__is_backend_busy(i))
+ continue;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+static int __check_queue_status_for_exit(void)
+{
+ pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
+ queue_info_map *ptr = NULL;
+ ptr = start;
+ int i = 0;
+ int c = 0;
+ int slot = -1;
+ for(i = 0; i < entries; i++)
+ {
+ if (ptr->queue_slot <= slot) {
+ ptr++;
+ continue;
+ }
+ else {
+ head[c] = ptr->head;
+ slot = ptr->queue_slot;
+ c++;
+ ptr++;
+ }
+ }
+ for(i = 0; i < num_of_backends; i++)
+ {
+ if (!head[i])
+ continue;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+gboolean exit_server(void *data)
+{
+ DBG("exit_server Start\n");
+ if (__check_backend_status_for_exit() &&
+ __check_queue_status_for_exit()) {
+ if (!getenv("PMS_STANDALONE")) {
+ g_main_loop_quit(mainloop);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static int __pkgcmd_read_proc(const char *path, char *buf, int size)
+{
+ int fd;
+ int ret;
+ if (buf == NULL || path == NULL)
+ return -1;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ ret = read(fd, buf, size - 1);
+ if (ret <= 0) {
+ close(fd);
+ return -1;
+ } else
+ buf[ret] = 0;
+ close(fd);
+ return ret;
+}
+
+static int __pkgcmd_find_pid_by_cmdline(const char *dname,
+ const char *cmdline, const char *apppath)
+{
+ int pid = 0;
+
+ if (strcmp(cmdline, apppath) == 0) {
+ pid = atoi(dname);
+ if (pid != getpgid(pid))
+ pid = 0;
+ }
+ return pid;
+}
+
+static int __pkgcmd_proc_iter_kill_cmdline(const char *apppath, int option)
+{
+ DIR *dp;
+ struct dirent *dentry;
+ int pid;
+ int ret;
+ char buf[1024] = {'\0'};
+ int pgid;
+
+ dp = opendir("/proc");
+ if (dp == NULL) {
+ return -1;
+ }
+
+ while ((dentry = readdir(dp)) != NULL) {
+ if (!isdigit(dentry->d_name[0]))
+ continue;
+
+ snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
+ ret = __pkgcmd_read_proc(buf, buf, sizeof(buf));
+ if (ret <= 0)
+ continue;
+
+ pid = __pkgcmd_find_pid_by_cmdline(dentry->d_name, buf, apppath);
+ if (pid > 0) {
+ if (option == 0) {
+ closedir(dp);
+ return pid;
+ }
+ pgid = getpgid(pid);
+ if (pgid <= 1) {
+ closedir(dp);
+ return -1;
+ }
+ if (killpg(pgid, SIGKILL) < 0) {
+ closedir(dp);
+ return -1;
+ }
+ closedir(dp);
+ return pid;
+ }
+ }
+ closedir(dp);
+ return 0;
+}
+
+static void __make_pid_info_file(char *req_key, int pid)
+{
+ FILE* file;
+ int fd;
+ char buf[MAX_PKG_TYPE_LEN] = {0};
+ char info_file[PATH_MAX] = {'\0'};
+
+ if(req_key == NULL)
+ return;
+
+ snprintf(info_file, PATH_MAX, "/tmp/%s", req_key);
+
+ DBG("info_path(%s)", info_file);
+ file = fopen(info_file, "w");
+ if (file == NULL) {
+ ERR("Couldn't open the file(%s)", info_file);
+ return;
+ }
+
+ snprintf(buf, MAX_PKG_TYPE_LEN, "%d\n", pid);
+ fwrite(buf, 1, strlen(buf), file);
+
+ fflush(file);
+ fd = fileno(file);
+ fsync(fd);
+ fclose(file);
+}
+
+static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
+{
+ char *pkgid;
+ char *exec;
+ int ret;
+ int pid = -1;
+
+ if (handle == NULL) {
+ perror("appinfo handle is NULL\n");
+ exit(1);
+ }
+ ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
+ if (ret) {
+ perror("Failed to get app exec path\n");
+ exit(1);
+ }
+ ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
+ if (ret) {
+ perror("Failed to get pkgid\n");
+ exit(1);
+ }
+
+ if (strcmp(user_data, "kill") == 0)
+ pid = __pkgcmd_proc_iter_kill_cmdline(exec, 1);
+ else if(strcmp(user_data, "check") == 0)
+ pid = __pkgcmd_proc_iter_kill_cmdline(exec, 0);
+
+ __make_pid_info_file(pkgid, pid);
+
+ return 0;
+}
+
+void free_user_context(user_ctx* ctx)
+{
+ char **env = NULL;
+ int i = 0;
+ if (!ctx)
+ return;
+ env = ctx->env;
+ //env variable ends by NULL element
+ while (env[i]) {
+ free(env[i]);
+ i++;
+ }
+ free(env);
+ env = NULL;
+ free(ctx);
+}
+
+int set_environement(user_ctx *ctx)
+{
+ int i = 0;
+ int res = 0;
+ char **env = NULL;
+ if (!ctx)
+ return -1;;
+ if (setgid(ctx->gid)) {
+ ERR("setgid failed: %d", errno);
+ return -1;
+ }
+ if (setuid(ctx->uid)) {
+ ERR("setuid failed: %d", errno);
+ return -1;
+ }
+ env = ctx->env;
+ //env variable ends by NULL element
+ while (env[i]) {
+ if (putenv(env[i]) != 0)
+ res = -1;
+ i++;
+ }
+ return res;
+}
+
+user_ctx* get_user_context(uid_t uid)
+{
+ /* we can use getpwnam because this is used only after a
+ * fork and just before an execv
+ * No concurrencial call can corrupt the data
+ * returned by getpwuid
+ */
+ user_ctx *context_res;
+ char **env = NULL;
+ struct passwd * pwd;
+ int len;
+ int ret = 0;
+
+ pwd = getpwuid(uid);
+ if (!pwd)
+ return NULL;
+
+ do {
+ context_res = (user_ctx *)malloc(sizeof(user_ctx));
+ if (!context_res) {
+ ret = -1;
+ break;
+ }
+ env = (char**)malloc(3* sizeof(char *));
+ if (!env) {
+ ret = -1;
+ break;
+ }
+ // Build environment context
+ len = snprintf(NULL,0, "HOME=%s", pwd->pw_dir);
+ env[0] = (char*)malloc((len + 1)* sizeof(char));
+ if(env[0] == NULL) {
+ ret = -1;
+ break;
+ }
+ sprintf(env[0], "HOME=%s", pwd->pw_dir);
+ len = snprintf(NULL,0, "USER=%s", pwd->pw_name);
+ env[1] = (char*)malloc((len + 1)* sizeof(char));
+ if(env[1] == NULL) {
+ ret = -1;
+ break;
+ }
+
+ sprintf(env[1], "USER=%s", pwd->pw_name);
+ env[2] = NULL;
+ } while (0);
+
+ if (ret == -1) {
+ free(context_res);
+ context_res = NULL;
+ int i = 0;
+ //env variable ends by NULL element
+ while (env && env[i]) {
+ free(env[i]);
+ i++;
+ }
+ free(env);
+ env = NULL;
+ } else {
+ context_res->env = env;
+ context_res->uid = uid;
+ context_res->gid = pwd->pw_gid;
+ }
+ return context_res;
+}
+
+static char **__generate_argv(const char *args)
+{
+ /* Create args vector
+ * req_id + pkgid + args
+ *
+ * vector size = # of args +
+ *(req_id + pkgid + NULL termination = 3)
+ * Last value must be NULL for execv.
+ */
+ gboolean ret_parse;
+ gint argcp;
+ gchar **argvp;
+ GError *gerr = NULL;
+ ret_parse = g_shell_parse_argv(args,
+ &argcp, &argvp, &gerr);
+ if (FALSE == ret_parse) {
+ DBG("Failed to split args: %s", args);
+ DBG("messsage: %s", gerr->message);
+ exit(1);
+ }
+
+ /* Setup argument !!! */
+ /*char **args_vector =
+ calloc(argcp + 4, sizeof(char *)); */
+ char **args_vector = calloc(argcp + 1, sizeof(char *));
+ if (args_vector == NULL) {
+ ERR("Out of memory");
+ exit(1);
+ }
+ /*args_vector[0] = strdup(backend_cmd);
+ args_vector[1] = strdup(item->req_id);
+ args_vector[2] = strdup(item->pkgid); */
+ int arg_idx;
+ for (arg_idx = 0; arg_idx < argcp; arg_idx++) {
+ /* args_vector[arg_idx+3] = argvp[arg_idx]; */
+ args_vector[arg_idx] = argvp[arg_idx];
+ }
+
+ /* dbg */
+ /*for(arg_idx = 0; arg_idx < argcp+3; arg_idx++) { */
+ for (arg_idx = 0; arg_idx < argcp + 1; arg_idx++) {
+ DBG(">>>>>> args_vector[%d]=%s",
+ arg_idx, args_vector[arg_idx]);
+ }
+
+ return args_vector;
+}
+
+static void __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid)
+{
+ user_ctx* user_context = get_user_context(uid);
+ if(!user_context) {
+ DBG("Failed to getenv for the user : %d", uid);
+ exit(1);
+ }
+ if(set_environement(user_context)){
+ DBG("Failed to set env for the user : %d", uid);
+ exit(1);
+ }
+ free_user_context(user_context);
+
+ /* Execute backend !!! */
+ int ret = execv(cmd, argv);
+
+ /* Code below: exec failure. Should not be happened! */
+ DBG(">>>>>> OOPS 2!!!");
+
+ /* g_strfreev(args_vector); *//* FIXME: causes error */
+
+ if (ret == -1) {
+ perror("fail to exec");
+ exit(1);
+ }
+}
+
+static void __process_install(pm_dbus_msg *item)
+{
+ char *backend_cmd;
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ backend_cmd = _get_backend_cmd(item->pkg_type);
+ if (backend_cmd == NULL)
+ return;
+
+ snprintf(args, sizeof(args), "%s -k %s -i %s", backend_cmd,
+ item->req_id, item->pkgid);
+ args_vector = __generate_argv(args);
+ args_vector[0] = backend_cmd;
+
+ __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
+}
+
+static void __process_reinstall(pm_dbus_msg *item)
+{
+ char *backend_cmd;
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ backend_cmd = _get_backend_cmd(item->pkg_type);
+ if (backend_cmd == NULL)
+ return;
+
+ snprintf(args, sizeof(args), "%s -k %s -r %s", backend_cmd,
+ item->req_id, item->pkgid);
+ args_vector = __generate_argv(args);
+ args_vector[0] = backend_cmd;
+
+ __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
+}
+
+static void __process_uninstall(pm_dbus_msg *item)
+{
+ char *backend_cmd;
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ backend_cmd = _get_backend_cmd(item->pkg_type);
+ if (backend_cmd == NULL)
+ return;
+
+ snprintf(args, sizeof(args), "%s -k %s -d %s", backend_cmd,
+ item->req_id, item->pkgid);
+ args_vector = __generate_argv(args);
+ args_vector[0] = backend_cmd;
+
+ __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
+}
+
+static void __process_move(pm_dbus_msg *item)
+{
+ char *backend_cmd;
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ backend_cmd = _get_backend_cmd(item->pkg_type);
+ if (backend_cmd == NULL)
+ return;
+
+ /* TODO: set movetype */
+ snprintf(args, sizeof(args), "%s -k %s -m %s -t %s", backend_cmd,
+ item->req_id, item->pkgid, item->args);
+ args_vector = __generate_argv(args);
+ args_vector[0] = backend_cmd;
+
+ __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
+}
+
+static void __process_enable(pm_dbus_msg *item)
+{
+ /* TODO */
+}
+
+static void __process_disable(pm_dbus_msg *item)
+{
+ /* TODO */
+}
+
+static void __process_getsize(pm_dbus_msg *item)
+{
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ snprintf(args, sizeof(args), "%s %s -k %s", item->pkgid, item->args,
+ item->req_id);
+ args_vector = __generate_argv(args);
+ __exec_with_arg_vector("/usr/bin/pkg_getsize", args_vector, item->uid);
+}
+
+static void __process_cleardata(pm_dbus_msg *item)
+{
+ char *backend_cmd;
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ backend_cmd = _get_backend_cmd(item->pkg_type);
+ if (backend_cmd == NULL)
+ return;
+
+ /* TODO: set movetype */
+ snprintf(args, sizeof(args), "%s -k %s -c %s", backend_cmd,
+ item->req_id, item->pkgid);
+ args_vector = __generate_argv(args);
+ args_vector[0] = backend_cmd;
+
+ __exec_with_arg_vector(backend_cmd, args_vector, item->uid);
+}
+
+static void __process_clearcache(pm_dbus_msg *item)
+{
+ char **args_vector;
+ char args[MAX_PKG_ARGS_LEN];
+
+ snprintf(args, sizeof(args), "%s", item->pkgid);
+ args_vector = __generate_argv(args);
+ __exec_with_arg_vector("/usr/bin/pkg_clearcache", args_vector,
+ item->uid);
+}
+
+static void __process_kill(pm_dbus_msg *item)
+{
+ int ret;
+ pkgmgrinfo_pkginfo_h handle;
+
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
+ &handle);
+ if (ret < 0) {
+ ERR("Failed to get handle");
+ return;
+ }
+
+ ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
+ __pkgcmd_app_cb, "kill", item->uid);
+ if (ret < 0)
+ ERR("pkgmgrinfo_appinfo_get_list() failed");
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+}
+
+static void __process_check(pm_dbus_msg *item)
+{
+ int ret;
+ pkgmgrinfo_pkginfo_h handle;
+
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(item->pkgid, item->uid,
+ &handle);
+ if (ret < 0) {
+ ERR("Failed to get handle");
+ return;
+ }
+
+ ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
+ __pkgcmd_app_cb, "check", item->uid);
+ if (ret < 0)
+ ERR("pkgmgrinfo_appinfo_get_list() failed");
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+}
+
+gboolean queue_job(void *data)
+{
+ pm_dbus_msg *item = NULL;
+ backend_info *ptr;
+ int x;
+
+ /* Pop a job from queue */
+ for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) {
+ if (__is_backend_busy(x))
+ continue;
+
+ item = _pm_queue_pop(x);
+ if (item && item->req_type != -1)
+ break;
+ free(item);
+ }
+
+ /* all backend messages queue are empty or busy */
+ if (x == num_of_backends)
+ return FALSE;
+
+ __set_backend_busy(x);
+ __set_recovery_mode(item->uid, item->pkgid, item->pkg_type);
+
+ /* fork */
+ _save_queue_status(item, "processing");
+ DBG("saved queue status. Now try fork()");
+ /*save pkg type and pkg name for future*/
+ strncpy(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN-1);
+ strncpy(ptr->pkgid, item->pkgid, MAX_PKG_NAME_LEN-1);
+ strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1);
+ ptr->uid = item->uid;
+ ptr->pid = fork();
+ DBG("child forked [%d] for request type [%d]", ptr->pid, item->req_type);
+
+ switch (ptr->pid) {
+ case 0: /* child */
+ switch (item->req_type) {
+ case PKGMGR_REQUEST_TYPE_INSTALL:
+ __process_install(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_REINSTALL:
+ __process_reinstall(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_UNINSTALL:
+ __process_uninstall(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_MOVE:
+ __process_move(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_ENABLE:
+ __process_enable(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_DISABLE:
+ __process_disable(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_GETSIZE:
+ __process_getsize(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_CLEARDATA:
+ __process_cleardata(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_CLEARCACHE:
+ __process_clearcache(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_KILL:
+ __process_kill(item);
+ break;
+ case PKGMGR_REQUEST_TYPE_CHECK:
+ __process_check(item);
+ break;
+ }
+ /* exit child */
+ _save_queue_status(item, "done");
+ exit(0);
+ break;
+
+ case -1:
+ fprintf(stderr, "Fail to execute_fork()\n");
+ exit(1);
+
+ default: /* parent */
+ DBG("parent exit\n");
+ _save_queue_status(item, "done");
+ break;
+ }
+
+ free(item);
+
+ return FALSE;
+}
+
+#define IS_WHITESPACE(CHAR) \
+((CHAR == ' ' || CHAR == '\t' || CHAR == '\r' || CHAR == '\n') ? TRUE : FALSE)
+
+void _app_str_trim(char *input)
+{
+ char *trim_str = input;
+
+ if (input == NULL)
+ return;
+
+ while (*input != 0) {
+ if (!IS_WHITESPACE(*input)) {
+ *trim_str = *input;
+ trim_str++;
+ }
+ input++;
+ }
+
+ *trim_str = 0;
+ return;
+}
+
+char *_get_backend_cmd(char *type)
+{
+ FILE *fp = NULL;
+ char buffer[1024] = { 0 };
+ char *command = NULL;
+ int size = 0;
+ fp = fopen(PKG_CONF_PATH, "r");
+ if (fp == NULL) {
+ return NULL;
+ }
+
+ char *path = NULL;
+ while (fgets(buffer, 1024, fp) != NULL) {
+ if (buffer[0] == '#')
+ continue;
+
+ _app_str_trim(buffer);
+
+ if ((path = strstr(buffer, PKG_BACKEND)) != NULL) {
+ DBG("buffer [%s]", buffer);
+ path = path + strlen(PKG_BACKEND);
+ DBG("path [%s]", path);
+
+ command =
+ (char *)malloc(sizeof(char) * strlen(path) +
+ strlen(type) + 1);
+ if (command == NULL) {
+ fclose(fp);
+ return NULL;
+ }
+
+ size = strlen(path) + strlen(type) + 1;
+ snprintf(command, size, "%s%s", path, type);
+ command[strlen(path) + strlen(type)] = '\0';
+ DBG("command [%s]", command);
+
+ if (fp != NULL)
+ fclose(fp);
+
+ return command;
+ }
+
+ memset(buffer, 0x00, 1024);
+ }
+
+ if (fp != NULL)
+ fclose(fp);
+
+ return NULL; /* cannot find proper command */
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *fp_status = NULL;
+ char buf[32] = { 0, };
+ pid_t pid;
+ char *backend_cmd = NULL;
+ char *backend_name = NULL;
+ int r;
+
+ DBG("server start");
+
+ if (argv[1] && (strcmp(argv[1], "init") == 0)) {
+ /* if current status is "processing",
+ execute related backend with '-r' option */
+ if (!(fp_status = fopen(STATUS_FILE, "r")))
+ return 0; /*if file is not exist, terminated. */
+ /* if processing <-- unintended termination */
+ if (fgets(buf, 32, fp_status) &&
+ strcmp(buf, "processing") == 0) {
+ pid = fork();
+ if (pid == 0) { /* child */
+ if (fgets(buf, 32, fp_status))
+ backend_cmd = _get_backend_cmd(buf);
+ if (!backend_cmd) { /* if NULL, */
+ DBG("fail to get backend command");
+ goto err;
+ }
+ backend_name =
+ strrchr(backend_cmd, '/');
+ if (!backend_name) {
+ DBG("fail to get backend name");
+ goto err;
+ }
+
+ execl(backend_cmd, backend_name, "-r",
+ NULL);
+ if (backend_cmd)
+ free(backend_cmd);
+ fprintf(fp_status, " ");
+err:
+ fclose(fp_status);
+ exit(13);
+ } else if (pid < 0) { /* error */
+ DBG("fork fail");
+ fclose(fp_status);
+ return 0;
+ } else { /* parent */
+
+ DBG("parent end\n");
+ fprintf(fp_status, " ");
+ fclose(fp_status);
+ return 0;
+ }
+ }
+ }
+
+ r = _pm_queue_init();
+ if (r) {
+ DBG("Queue Initialization Failed\n");
+ return -1;
+ }
+
+ r = __init_backend_info();
+ if (r) {
+ DBG("backend info init failed");
+ return -1;
+ }
+
+ r = __init_request_handler();
+ if (r) {
+ ERR("dbus init failed");
+ return -1;
+ }
+
+ if (__register_signal_handler()) {
+ ERR("failed to register signal handler");
+ return -1;
+ }
+
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init();
+#endif
+ mainloop = g_main_loop_new(NULL, FALSE);
+ if (!mainloop) {
+ ERR("g_main_loop_new failed");
+ return -1;
+ }
+
+ DBG("Main loop is created.");
+
+ g_main_loop_run(mainloop);
+
+ DBG("Quit main loop.");
+ __fini_request_handler();
+ __fini_backend_info();
+ _pm_queue_final();
+
+ DBG("package manager server terminated.");
+
+ return 0;
+}
--- /dev/null
+/*
+ * slp-pkgmgr
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pkgmgr-server.h"
+#include "pm-queue.h"
+
+#define BACKEND_INFO_DIR "/etc/package-manager/backend"
+
+static pm_queue_data *__get_head_from_pkgtype(const char *pkg_type);
+static void __update_head_from_pkgtype(pm_queue_data *data);
+static int __entry_exist(char *backend);
+static int __is_pkg_supported(const char *pkgtype);
+
+queue_info_map *start = NULL;
+int entries = 0;
+int slot = 0;
+int num_of_backends = 0;
+
+/*Function to check whether a particular package type
+is supported or not. It parses the queue info map
+to get the information.
+It will prevent the accidental hanging of server.
+Returns 1 if found.*/
+static int __is_pkg_supported(const char *pkgtype)
+{
+ queue_info_map *ptr = NULL;
+ ptr = start;
+ int i = 0;
+ for(i = 0; i < entries; i++)
+ {
+ if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
+ return 1;
+ else {
+ ptr++;
+ continue;
+ }
+ }
+ return 0;
+}
+
+/*tells whether a particular backend exists in the
+* info map or not.
+* on Success it return the queue slot of the already present entry
+* on Failure -1 is returned*/
+static int __entry_exist(char *backend)
+{
+ queue_info_map *ptr = NULL;
+ ptr = start;
+ int i = 0;
+ for(i = 0; i < entries; i++)
+ {
+ if (!strncmp(ptr->backend, backend, MAX_PKG_NAME_LEN))
+ return ptr->queue_slot;
+ else {
+ ptr++;
+ continue;
+ }
+ }
+ return -1;
+}
+
+/*In case of first push, it updates the queue head
+and copies it to all duplicate entries in queue info map*/
+static void __update_head_from_pkgtype(pm_queue_data *data)
+{
+ queue_info_map *ptr = NULL;
+ ptr = start;
+ int slot = -1;
+ int i = 0;
+ for(i = 0; i < entries; i++)
+ {
+ if (!strncmp(ptr->pkgtype, data->msg->pkg_type, MAX_PKG_TYPE_LEN)) {
+ ptr->head = data;
+ slot = ptr->queue_slot;
+ }
+ else {
+ ptr++;
+ continue;
+ }
+ }
+ /*update head for each duplicate entry*/
+ ptr = start;
+ for(i = 0; i < entries; i++)
+ {
+ if(ptr->queue_slot == slot && !ptr->head) {
+ ptr->head = data;
+ }
+ ptr++;
+ }
+ return;
+}
+
+/*Gets the queue head based on pkg type*/
+static pm_queue_data *__get_head_from_pkgtype(const char *pkg_type)
+{
+ queue_info_map *ptr = NULL;
+ ptr = start;
+ int i = 0;
+ for(i = 0; i < entries; i++)
+ {
+ if (!strncmp(ptr->pkgtype, pkg_type, MAX_PKG_TYPE_LEN))
+ return ptr->head;
+ else {
+ ptr++;
+ continue;
+ }
+ }
+ return NULL;
+
+}
+
+int _pm_queue_init(void)
+{
+ /*Find the num of backends currently supported and initialize
+ that many queues. It is dynamically determined.*/
+ struct dirent **namelist;
+ struct stat fileinfo;
+ queue_info_map *ptr = NULL;
+ int n = 0;
+ int c = 0;
+ int i = 0;
+ int ret = 0;
+ char abs_filename[MAX_PKG_NAME_LEN] = {'\0'};
+ char buf[MAX_PKG_NAME_LEN] = {'\0'};
+ n = scandir(BACKEND_INFO_DIR, &namelist, NULL, alphasort);
+ if (n < 0) {
+ perror("scandir");
+ return -1;
+ }
+ i = n;
+ /*Find number of backends (symlinks + executables)
+ The /usr/etc/package-manager/backend dir should not conatin
+ any other file except the backends.*/
+ while(n--)
+ {
+ if(!strcmp(namelist[n]->d_name, ".") ||
+ !strcmp(namelist[n]->d_name, ".."))
+ continue;
+ snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
+ BACKEND_INFO_DIR, namelist[n]->d_name);
+ if (lstat(abs_filename, &fileinfo)) {
+ perror("lstat");
+ continue;
+ }
+ if (S_ISDIR(fileinfo.st_mode))
+ continue;
+ c++;
+ memset(abs_filename, 0x00, MAX_PKG_NAME_LEN);
+ }
+ /*Add entries to info map.*/
+ ptr = (queue_info_map*)calloc(c , sizeof(queue_info_map));
+ memset(ptr, '\0', c * sizeof(queue_info_map));
+ start = ptr;
+ for(n = 0; n < c ; n++)
+ {
+ ptr->backend[0] = '\0';
+ ptr->head = NULL;
+ ptr->queue_slot = -2;/*-1 can be error return*/
+ ptr->pkgtype[0] = '\0';
+ ptr++;
+ }
+ n = i;
+ ptr = start;
+ while(n--)
+ {
+ if(!strcmp(namelist[n]->d_name, ".") ||
+ !strcmp(namelist[n]->d_name, ".."))
+ continue;
+ snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
+ BACKEND_INFO_DIR, namelist[n]->d_name);
+ if (lstat(abs_filename, &fileinfo) < 0) {
+ perror(abs_filename);
+ return -1;
+ }
+ if (S_ISDIR(fileinfo.st_mode))
+ continue;
+ /*Found backend*/
+ if (S_ISLNK(fileinfo.st_mode)) {
+ /*found a symlink*/
+ ret = readlink(abs_filename, buf, MAX_PKG_NAME_LEN - 1);
+ if (ret == -1) {
+ perror("readlink");
+ return -1;
+ }
+ buf[ret] = '\0';
+ }
+ /*executable*/
+ else {
+ snprintf(buf, sizeof(buf), "%s", abs_filename);
+ }
+ ret = __entry_exist(buf);
+ if (ret == -1) {
+ snprintf(ptr->backend, sizeof(ptr->backend), "%s", buf);
+ snprintf(ptr->pkgtype, sizeof(ptr->pkgtype), "%s", namelist[n]->d_name);
+ ptr->queue_slot = slot;
+ ptr->head = NULL;
+ entries++;
+ slot++;
+ ptr++;
+ }
+ else {
+ snprintf(ptr->backend, sizeof(ptr->backend), "%s", buf);
+ snprintf(ptr->pkgtype, sizeof(ptr->pkgtype), "%s", namelist[n]->d_name);
+ ptr->queue_slot = ret;
+ ptr->head = NULL;
+ entries++;
+ ptr++;
+ }
+ free(namelist[n]);
+ memset(buf, 0x00, MAX_PKG_NAME_LEN);
+ continue;
+ }
+ free(namelist);
+ num_of_backends = slot;
+
+#ifdef DEBUG_INFO
+ /*Debug info*/
+ DBG("Queue Info Map");
+ DBG("Number of Backends is %d", num_of_backends);
+ DBG("Number of Entries is %d", entries);
+ DBG("Backend\tType\tSlot\tHead");
+ ptr = start;
+ for(n = 0; n < entries; n++)
+ {
+ DBG("%s\t%s\t%d\t%p", ptr->backend, ptr->pkgtype, ptr->queue_slot, ptr->head);
+ ptr++;
+ }
+#endif
+
+ return 0;
+}
+
+int _pm_queue_push(uid_t uid, const char *req_id, int req_type,
+ const char *pkg_type, const char *pkgid, const char *args)
+{
+ pm_queue_data *data = NULL;
+ pm_queue_data *cur = NULL;
+ pm_queue_data *tmp = NULL;
+ int ret = 0;
+ ret = __is_pkg_supported(pkg_type);
+ if (ret == 0)
+ return -1;
+
+ cur = __get_head_from_pkgtype(pkg_type);
+ tmp = cur;
+
+ /* TODO: use glist */
+ data = _add_node();
+ if (!data) { /* fail to allocate mem */
+ ERR("Fail to allocate memory\n");
+ return -1;
+ }
+
+ snprintf(data->msg->req_id, sizeof(data->msg->req_id), "%s", req_id);
+ data->msg->req_type = req_type;
+ data->msg->uid = uid;
+ snprintf(data->msg->pkg_type, sizeof(data->msg->pkg_type), "%s", pkg_type);
+ snprintf(data->msg->pkgid, sizeof(data->msg->pkgid), "%s", pkgid);
+ snprintf(data->msg->args, sizeof(data->msg->args), "%s", args);
+
+ data->next = NULL;
+
+ if (cur == NULL) {
+ /* first push */
+ cur = data;
+ __update_head_from_pkgtype(data);
+ }
+ else {
+ while (tmp->next)
+ tmp = tmp->next;
+
+ tmp->next = data;
+ }
+ return 0;
+}
+
+/*pop request from queue slot "position" */
+pm_dbus_msg *_pm_queue_pop(int position)
+{
+ pm_dbus_msg *ret;
+ pm_queue_data *cur = NULL;
+ pm_queue_data *saveptr = NULL;
+ queue_info_map *ptr = NULL;
+ int i = 0;
+
+ ret = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
+ if (!ret) {
+ ERR("Mem alloc error");
+ return NULL;
+ }
+ memset(ret, 0x00, sizeof(pm_dbus_msg));
+ ptr = start;
+ for(i = 0; i < entries; i++)
+ {
+ if (ptr->queue_slot == position) {
+ cur = ptr->head;
+ break;
+ }
+ ptr++;
+ }
+
+ if (!cur) { /* queue is empty */
+ ret->req_type = -1;
+ return ret;
+ }
+
+ snprintf(ret->req_id, sizeof(ret->req_id), "%s", cur->msg->req_id);
+ ret->req_type = cur->msg->req_type;
+ ret->uid = cur->msg->uid;
+ snprintf(ret->pkg_type, sizeof(ret->pkg_type), "%s", cur->msg->pkg_type);
+ snprintf(ret->pkgid, sizeof(ret->pkgid), "%s", cur->msg->pkgid);
+ snprintf(ret->args, sizeof(ret->args), "%s", cur->msg->args);
+
+ ptr->head = cur->next;
+ saveptr = ptr->head;
+ cur->next = NULL;
+ free(cur->msg);
+ free(cur);
+ /*update head for each duplicate queue entry*/
+ ptr = start;
+ for(i = 0; i < entries; i++)
+ {
+ if(ptr->queue_slot == position) {
+ ptr->head = saveptr;
+ }
+ ptr++;
+ }
+ return ret;
+}
+
+/*populate an array of all queue heads and delete them one by one*/
+void _pm_queue_final()
+{
+ int c = 0;
+ int i = 0;
+ int slot = -1;
+ pm_queue_data *cur = NULL;
+ pm_queue_data *tail = NULL;
+ pm_queue_data *prev = NULL;
+ pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
+ queue_info_map *ptr = NULL;
+ ptr = start;
+
+ for(i = 0; i < num_of_backends; i++)
+ {
+ head[i] = NULL;
+ }
+
+ for(i = 0; i < entries; i++)
+ {
+ if (ptr->queue_slot <= slot) {
+ ptr++;
+ continue;
+ }
+ else {
+ head[c] = ptr->head;
+ slot = ptr->queue_slot;
+ c++;
+ ptr++;
+ }
+ }
+
+ c = 0;
+ while(c < num_of_backends) {
+ if (!head[c]) { /* in case of head is NULL */
+ ERR("queue is NULL");
+ c = c + 1;
+ continue;
+ }
+
+ while (head[c]->next) {
+ cur = head[c]->next;
+
+ while (cur->next) {
+ prev = cur;
+ cur = cur->next;
+ }
+
+ tail = cur;
+
+ free(tail->msg);
+ free(tail);
+ prev->next = NULL;
+ }
+
+ free(head[c]->msg);
+ free(head[c]);
+
+ head[c] = NULL;
+ c = c + 1;
+ }
+ /*Free the info map*/
+ if (start) {
+ free(start);
+ start = NULL;
+ }
+}
+
+pm_queue_data *_add_node()
+{
+ pm_queue_data *newnode = NULL;
+
+ newnode = (pm_queue_data *) malloc(sizeof(pm_queue_data));
+ if (!newnode) { /* if NULL */
+ ERR("Mem alloc error");
+ return NULL;
+ }
+ memset(newnode, 0x00, sizeof(pm_queue_data));
+
+ newnode->msg = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
+ if (!newnode->msg) {
+ ERR("Mem alloc error");
+ free(newnode);
+ return NULL;
+ }
+ memset(newnode->msg, 0x00, sizeof(pm_dbus_msg));
+
+ return newnode;
+}
+
+void _pm_queue_delete(pm_dbus_msg *item)
+{
+ /* Assume that pacakge name is unique */
+ pm_queue_data *cur = NULL;
+ pm_queue_data *prev = NULL;
+ cur = __get_head_from_pkgtype(item->pkg_type);
+ prev = cur;
+ if (cur) {
+ while (cur->next) {
+ if (!strcmp(item->pkgid, cur->msg->pkgid)) {
+ prev->next = cur->next;
+ free(cur->msg);
+ free(cur);
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+}
+
+void _save_queue_status(pm_dbus_msg *item, char *status)
+{
+ FILE *fp_status = NULL;
+
+ fp_status = fopen(STATUS_FILE, "w"); /* overwrite always */
+ if (!fp_status) {
+ ERR("Can't open status file:%s", STATUS_FILE);
+ return;
+ }
+
+ fprintf(fp_status, "%s\n", status);
+ fprintf(fp_status, "%s\n", item->pkg_type);
+
+ fsync(fileno(fp_status));
+
+ fclose(fp_status);
+}
+
+void _print_queue(int position)
+{
+ pm_queue_data *cur = NULL;
+ queue_info_map *ptr = start;
+ int i = 0;
+ for(i =0; i < entries; i++)
+ {
+ if (ptr->queue_slot == position) {
+ cur = ptr->head;
+ break;
+ }
+ ptr++;
+ }
+ int index = 1;
+ if (!cur) {
+ return;
+ }
+
+ while (cur) {
+ index++;
+ cur = cur->next;
+ }
+}
--- /dev/null
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "comm_config.h"
+#include "pm-queue.h"
+#include "pkgmgr-server.h"
+#include "package-manager.h"
+#include "package-manager-debug.h"
+
+static const char instropection_xml[] =
+ "<node>"
+ " <interface name='org.tizen.pkgmgr'>"
+ " <method name='install'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgtype' direction='in'/>"
+ " <arg type='s' name='pkgpath' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " <arg type='s' name='reqkey' direction='out'/>"
+ " </method>"
+ " <method name='reinstall'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgtype' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " <arg type='s' name='reqkey' direction='out'/>"
+ " </method>"
+ " <method name='uninstall'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgtype' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " <arg type='s' name='reqkey' direction='out'/>"
+ " </method>"
+ " <method name='move'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgtype' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " <arg type='s' name='reqkey' direction='out'/>"
+ " </method>"
+ " <method name='enable_pkg'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='disable_pkg'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='enable_app'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='appid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='disable_app'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='appid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='getsize'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='get_type' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " <arg type='s' name='reqkey' direction='out'/>"
+ " </method>"
+ " <method name='cleardata'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgtype' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='clearcache'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='kill'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " <method name='check'>"
+ " <arg type='u' name='uid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='ret' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+static GDBusNodeInfo *instropection_data;
+static guint reg_id;
+static guint owner_id;
+
+static char *__generate_reqkey(const char *pkgid)
+{
+ struct timeval tv;
+ long curtime;
+ char timestr[MAX_PKG_ARGS_LEN];
+ char *str_req_key;
+ int size;
+
+ gettimeofday(&tv, NULL);
+ curtime = tv.tv_sec * 1000000 + tv.tv_usec;
+ snprintf(timestr, sizeof(timestr), "%ld", curtime);
+
+ size = strlen(pkgid) + strlen(timestr) + 2;
+ str_req_key = (char *)calloc(size, sizeof(char));
+ if (str_req_key == NULL) {
+ DBG("calloc failed");
+ return NULL;
+ }
+ snprintf(str_req_key, size, "%s_%s", pkgid, timestr);
+
+ return str_req_key;
+}
+
+static int __handle_request_install(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgtype = NULL;
+ char *pkgpath = NULL;
+ char *reqkey;
+
+ g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgpath);
+ if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgpath == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+ return -1;
+ }
+
+ reqkey = __generate_reqkey(pkgpath);
+ if (reqkey == NULL)
+ return -1;
+ if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_INSTALL, pkgtype,
+ pkgpath, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+ free(reqkey);
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+ free(reqkey);
+
+ return 0;
+}
+
+static int __handle_request_reinstall(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgtype = NULL;
+ char *pkgid = NULL;
+ char *reqkey;
+
+ g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+ return -1;
+ }
+
+ reqkey = __generate_reqkey(pkgid);
+ if (reqkey == NULL)
+ return -1;
+ if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_REINSTALL, pkgtype,
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+ free(reqkey);
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+ free(reqkey);
+
+ return 0;
+}
+
+static int __handle_request_uninstall(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgtype = NULL;
+ char *pkgid = NULL;
+ char *reqkey;
+
+ g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+ return -1;
+ }
+
+ reqkey = __generate_reqkey(pkgid);
+ if (reqkey == NULL)
+ return -1;
+ if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_UNINSTALL, pkgtype,
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+ free(reqkey);
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+ free(reqkey);
+
+ return 0;
+}
+
+static int __handle_request_move(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgtype = NULL;
+ char *pkgid = NULL;
+ char *reqkey;
+
+ g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+ return -1;
+ }
+
+ reqkey = __generate_reqkey(pkgid);
+ if (reqkey == NULL)
+ return -1;
+ if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_MOVE, pkgtype,
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+ free(reqkey);
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+ free(reqkey);
+
+ return 0;
+}
+
+static int __handle_request_enable(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE, "pkg",
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static int __handle_request_disable(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE, "pkg",
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static int __handle_request_getsize(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+ int get_type = -1;
+ char *reqkey;
+ char buf[4];
+
+ g_variant_get(parameters, "(u&si)", &target_uid, &pkgid, &get_type);
+ if (target_uid == (uid_t)-1 || pkgid == NULL || get_type == -1) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ECOMM, ""));
+ return -1;
+ }
+
+ reqkey = __generate_reqkey(pkgid);
+ if (reqkey == NULL)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "%d", get_type);
+ if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_GETSIZE, "getsize",
+ pkgid, buf)) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_ESYSTEM, ""));
+ free(reqkey);
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(is)", PKGMGR_R_OK, reqkey));
+ free(reqkey);
+
+ return 0;
+}
+
+static int __handle_request_cleardata(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgtype = NULL;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_CLEARDATA, pkgtype,
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static int __handle_request_clearcache(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_CLEARCACHE,
+ "clearcache", pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static int __handle_request_kill(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_KILL, "pkg",
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static int __handle_request_check(uid_t uid,
+ GDBusMethodInvocation *invocation, GVariant *parameters)
+{
+ uid_t target_uid = (uid_t)-1;
+ char *pkgid = NULL;
+
+ g_variant_get(parameters, "(u&s)", &target_uid, &pkgid);
+ if (target_uid == (uid_t)-1 || pkgid == NULL) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ECOMM));
+ return -1;
+ }
+
+ if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_CHECK, "pkg",
+ pkgid, "")) {
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_ESYSTEM));
+ return -1;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", PKGMGR_R_OK));
+
+ return 0;
+}
+
+static uid_t __get_caller_uid(GDBusConnection *connection, const char *name)
+{
+ GError *err = NULL;
+ GVariant *result;
+ uid_t uid;
+
+ result = g_dbus_connection_call_sync(connection,
+ "org.freedesktop.DBus", "/org/freedesktop/DBus",
+ "org.freedesktop.DBus", "GetConnectionUnixUser",
+ g_variant_new("(s)", name), NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+ if (result == NULL) {
+ ERR("failed to get caller uid: %s", err->message);
+ g_error_free(err);
+ return (uid_t)-1;
+ }
+
+ g_variant_get(result, "(u)", &uid);
+
+ return uid;
+}
+
+static void __handle_method_call(GDBusConnection *connection,
+ const gchar *sender, const gchar *object_path,
+ const gchar *interface_name, const gchar *method_name,
+ GVariant *parameters, GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret;
+ uid_t uid;
+
+ uid = __get_caller_uid(connection,
+ g_dbus_method_invocation_get_sender(invocation));
+ if (uid == (uid_t)-1)
+ return;
+
+ if (g_strcmp0(method_name, "install") == 0)
+ ret = __handle_request_install(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "reinstall") == 0)
+ ret = __handle_request_reinstall(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "uninstall") == 0)
+ ret = __handle_request_uninstall(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "cleardata") == 0)
+ ret = __handle_request_cleardata(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "move") == 0)
+ ret = __handle_request_move(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "enable") == 0)
+ ret = __handle_request_enable(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "disable") == 0)
+ ret = __handle_request_disable(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "getsize") == 0)
+ ret = __handle_request_getsize(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "clearcache") == 0)
+ ret = __handle_request_clearcache(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "kill") == 0)
+ ret = __handle_request_kill(uid, invocation, parameters);
+ else if (g_strcmp0(method_name, "check") == 0)
+ ret = __handle_request_check(uid, invocation, parameters);
+ else
+ ret = -1;
+
+ if (ret == 0)
+ g_idle_add(queue_job, NULL);
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ __handle_method_call,
+ NULL,
+ NULL,
+};
+
+static void __on_bus_acquired(GDBusConnection *connection, const gchar *name,
+ gpointer user_data)
+{
+ GError *err = NULL;
+
+ DBG("on bus acquired");
+
+ reg_id = g_dbus_connection_register_object(connection,
+ COMM_PKGMGR_DBUS_OBJECT_PATH,
+ instropection_data->interfaces[0],
+ &interface_vtable, NULL, NULL, &err);
+
+ if (reg_id == 0) {
+ ERR("failed to register object: %s", err->message);
+ g_error_free(err);
+ }
+}
+
+static void __on_name_acquired(GDBusConnection *connection, const gchar *name,
+ gpointer user_data)
+{
+ DBG("on name acquired: %s", name);
+}
+
+static void __on_name_lost(GDBusConnection *connection, const gchar *name,
+ gpointer user_data)
+{
+ DBG("on name lost: %s", name);
+}
+
+int __init_request_handler(void)
+{
+ instropection_data = g_dbus_node_info_new_for_xml(instropection_xml, NULL);
+
+ owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, COMM_PKGMGR_DBUS_SERVICE,
+ G_BUS_NAME_OWNER_FLAGS_NONE, __on_bus_acquired,
+ __on_name_acquired, __on_name_lost, NULL, NULL);
+
+ return 0;
+}
+
+void __fini_request_handler(void)
+{
+ g_bus_unown_name(owner_id);
+ g_dbus_node_info_unref(instropection_data);
+}