seperate server from slp-pkgmr to prevent cyclic dependency 01/50501/2 accepted/tizen/mobile/20151031.105506 accepted/tizen/tv/20151031.110236 accepted/tizen/wearable/20151031.110514 submit/tizen/20151030.025153 submit/tizen/20151030.025235
authorjongmyeongko <jongmyeong.ko@samsung.com>
Thu, 29 Oct 2015 10:19:22 +0000 (19:19 +0900)
committerjongmyeongko <jongmyeong.ko@samsung.com>
Thu, 29 Oct 2015 10:25:33 +0000 (19:25 +0900)
Change-Id: I6ab194c243f77fa18fe0e528c88dcfbc91d1b5e4
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
13 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
include/pkgmgr-server.h [new file with mode: 0644]
include/pm-queue.h [new file with mode: 0644]
org.tizen.pkgmgr.conf.in [new file with mode: 0644]
org.tizen.pkgmgr.service.in [new file with mode: 0644]
packaging/pkgmgr-server.manifest [new file with mode: 0644]
packaging/pkgmgr-server.spec [new file with mode: 0644]
queue_status [new file with mode: 0644]
src/pkgmgr-server.c [new file with mode: 0644]
src/pm-queue.c [new file with mode: 0644]
src/request.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..d908bc1
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Jayoun Lee <airjany@samsung.com>
+Sewook Park <sewook7.park@samsung.com>
+Jaeho Lee <jaeho81.lee@samsung.com>
+Shobhit Srivastava <shobhit.s@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..acb751b
--- /dev/null
@@ -0,0 +1,43 @@
+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/)
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..a06208b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+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.
+
diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h
new file mode 100644 (file)
index 0000000..69cca87
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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_ */
diff --git a/include/pm-queue.h b/include/pm-queue.h
new file mode 100644 (file)
index 0000000..fac45d5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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_ */
diff --git a/org.tizen.pkgmgr.conf.in b/org.tizen.pkgmgr.conf.in
new file mode 100644 (file)
index 0000000..266985f
--- /dev/null
@@ -0,0 +1,22 @@
+<?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>
diff --git a/org.tizen.pkgmgr.service.in b/org.tizen.pkgmgr.service.in
new file mode 100644 (file)
index 0000000..38c9534
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+User=root
+Name=org.tizen.pkgmgr
+Exec=@PREFIX@/bin/pkgmgr-server
diff --git a/packaging/pkgmgr-server.manifest b/packaging/pkgmgr-server.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/packaging/pkgmgr-server.spec b/packaging/pkgmgr-server.spec
new file mode 100644 (file)
index 0000000..80b7543
--- /dev/null
@@ -0,0 +1,61 @@
+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}
diff --git a/queue_status b/queue_status
new file mode 100644 (file)
index 0000000..5baa80c
--- /dev/null
@@ -0,0 +1 @@
+This file is for creating required directory.
diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c
new file mode 100644 (file)
index 0000000..350cb0e
--- /dev/null
@@ -0,0 +1,1145 @@
+/*
+ * 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;
+}
diff --git a/src/pm-queue.c b/src/pm-queue.c
new file mode 100644 (file)
index 0000000..0100a9d
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * 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;
+       }
+}
diff --git a/src/request.c b/src/request.c
new file mode 100644 (file)
index 0000000..7b1d8d4
--- /dev/null
@@ -0,0 +1,563 @@
+#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);
+}