From c140726ab76404a39014cbda047de65460b5dfff Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Thu, 29 Oct 2015 19:19:22 +0900 Subject: [PATCH 2/3] seperate server from slp-pkgmr to prevent cyclic dependency Change-Id: I6ab194c243f77fa18fe0e528c88dcfbc91d1b5e4 Signed-off-by: jongmyeongko --- AUTHORS | 4 + CMakeLists.txt | 43 ++ LICENSE | 204 +++++++ include/pkgmgr-server.h | 83 +++ include/pm-queue.h | 60 ++ org.tizen.pkgmgr.conf.in | 22 + org.tizen.pkgmgr.service.in | 4 + packaging/pkgmgr-server.manifest | 5 + packaging/pkgmgr-server.spec | 61 ++ queue_status | 1 + src/pkgmgr-server.c | 1145 ++++++++++++++++++++++++++++++++++++++ src/pm-queue.c | 509 +++++++++++++++++ src/request.c | 563 +++++++++++++++++++ 13 files changed, 2704 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 include/pkgmgr-server.h create mode 100644 include/pm-queue.h create mode 100644 org.tizen.pkgmgr.conf.in create mode 100644 org.tizen.pkgmgr.service.in create mode 100644 packaging/pkgmgr-server.manifest create mode 100644 packaging/pkgmgr-server.spec create mode 100644 queue_status create mode 100644 src/pkgmgr-server.c create mode 100644 src/pm-queue.c create mode 100644 src/request.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..d908bc1 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Jayoun Lee +Sewook Park +Jaeho Lee +Shobhit Srivastava diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..acb751b --- /dev/null +++ b/CMakeLists.txt @@ -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 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 index 0000000..69cca87 --- /dev/null +++ b/include/pkgmgr-server.h @@ -0,0 +1,83 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 + +#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 index 0000000..fac45d5 --- /dev/null +++ b/include/pm-queue.h @@ -0,0 +1,60 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 index 0000000..266985f --- /dev/null +++ b/org.tizen.pkgmgr.conf.in @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/org.tizen.pkgmgr.service.in b/org.tizen.pkgmgr.service.in new file mode 100644 index 0000000..38c9534 --- /dev/null +++ b/org.tizen.pkgmgr.service.in @@ -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 index 0000000..a76fdba --- /dev/null +++ b/packaging/pkgmgr-server.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/pkgmgr-server.spec b/packaging/pkgmgr-server.spec new file mode 100644 index 0000000..80b7543 --- /dev/null +++ b/packaging/pkgmgr-server.spec @@ -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 index 0000000..5baa80c --- /dev/null +++ b/queue_status @@ -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 index 0000000..350cb0e --- /dev/null +++ b/src/pkgmgr-server.c @@ -0,0 +1,1145 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#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<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 index 0000000..0100a9d --- /dev/null +++ b/src/pm-queue.c @@ -0,0 +1,509 @@ +/* + * slp-pkgmgr + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee , Shobhit Srivastava + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 index 0000000..7b1d8d4 --- /dev/null +++ b/src/request.c @@ -0,0 +1,563 @@ +#include +#include + +#include +#include + +#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[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; +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); +} -- 2.7.4 From 22b76b196ef6233af9d1a93512f324276667adc6 Mon Sep 17 00:00:00 2001 From: VBS Date: Tue, 3 Nov 2015 20:32:33 +0900 Subject: [PATCH 3/3] implement TEP install, update [app-installer][pkgmgr-info][pkgmgr-server][pkgmgr-tool][slp-pkgmgr] Signed-off-by: VBS Change-Id: Ie376dd71bb487229d165e36592f20987a6ed5128 --- src/pkgmgr-server.c | 10 +++++--- src/request.c | 67 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 350cb0e..bc1b2c8 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -691,6 +691,7 @@ static char **__generate_argv(const char *args) 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); @@ -702,6 +703,7 @@ static void __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid) free_user_context(user_context); /* Execute backend !!! */ + int ret = execv(cmd, argv); /* Code below: exec failure. Should not be happened! */ @@ -719,14 +721,15 @@ static void __process_install(pm_dbus_msg *item) { char *backend_cmd; char **args_vector; - char args[MAX_PKG_ARGS_LEN]; + char args[MAX_PKG_ARGS_LEN] = {'\0', }; 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); + snprintf(args, sizeof(args), "%s -k %s -i %s %s", backend_cmd, + item->req_id, item->pkgid, item->args); + args_vector = __generate_argv(args); args_vector[0] = backend_cmd; @@ -908,6 +911,7 @@ gboolean queue_job(void *data) 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); diff --git a/src/request.c b/src/request.c index 7b1d8d4..9e59939 100644 --- a/src/request.c +++ b/src/request.c @@ -17,6 +17,7 @@ static const char instropection_xml[] = " " " " " " + " " " " " " " " @@ -124,31 +125,75 @@ static int __handle_request_install(uid_t uid, uid_t target_uid = (uid_t)-1; char *pkgtype = NULL; char *pkgpath = NULL; - char *reqkey; + char *args = NULL; + char *reqkey = NULL; + gchar **tmp_args = NULL; + gsize args_count; + int ret = -1; + GVariant *value; + gchar *str; + int i = 0; + int len = 0; + + g_variant_get(parameters, "(u&s&s@as)", &target_uid, &pkgtype, &pkgpath, &value); + tmp_args = (gchar **)g_variant_get_strv(value, &args_count); + + for (i = 0; i < args_count; i++) + len = len + strlen(tmp_args[i]) + 1; + + args = (char *)calloc(len, sizeof(char)); + if (args == NULL) { + ERR("calloc failed"); + ret = -1; + goto catch; + } + + for (i = 0; i < args_count; i++) { + strncat(args, tmp_args[i], strlen(tmp_args[i])); + strncat(args, " ", strlen(" ")); + } - g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgpath); - if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgpath == NULL) { + if (target_uid == (uid_t)-1 || pkgtype == NULL) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(is)", PKGMGR_R_ECOMM, "")); - return -1; + ret = -1; + goto catch; + } + + if (pkgpath == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); + ret = -1; + goto catch; } reqkey = __generate_reqkey(pkgpath); - if (reqkey == NULL) - return -1; + if (reqkey == NULL) { + ret = -1; + goto catch; + } + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_INSTALL, pkgtype, - pkgpath, "")) { + pkgpath, args)) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); - free(reqkey); - return -1; + ret = -1; + goto catch; } g_dbus_method_invocation_return_value(invocation, g_variant_new("(is)", PKGMGR_R_OK, reqkey)); - free(reqkey); - return 0; + ret = 0; + +catch: + if (reqkey) + free(reqkey); + + if (args) + free(args); + + return ret; } static int __handle_request_reinstall(uid_t uid, -- 2.7.4