From c140726ab76404a39014cbda047de65460b5dfff Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Thu, 29 Oct 2015 19:19:22 +0900 Subject: [PATCH 01/16] 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 02/16] 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 From 0c8f07f79c49692a3160ebb5a40db99776302675 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 26 Nov 2015 16:41:34 +0900 Subject: [PATCH 03/16] Add functionality to support sending reply at specific point store GDBusMethodInvocation object with 'req_key' in 'req_table' pkgmgr-server calls '__return_value_to_caller' after job finished Change-Id: I026fceca63648b5dd7e9d4e8a1182c32869c1dca Signed-off-by: Sangyoon Jang --- include/pkgmgr-server.h | 1 + src/request.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 69cca87..6bdafe2 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -77,6 +77,7 @@ typedef struct backend_info_t { char *_get_backend_cmd(char *type); gboolean queue_job(void *data); +int __return_value_to_caller(const char *req_key, GVariant *result); int __init_request_handler(void); void __fini_request_handler(void); diff --git a/src/request.c b/src/request.c index 9e59939..cbce8dd 100644 --- a/src/request.c +++ b/src/request.c @@ -95,6 +95,7 @@ static const char instropection_xml[] = static GDBusNodeInfo *instropection_data; static guint reg_id; static guint owner_id; +static GHashTable *req_table; static char *__generate_reqkey(const char *pkgid) { @@ -553,6 +554,23 @@ static void __handle_method_call(GDBusConnection *connection, g_idle_add(queue_job, NULL); } +int __return_value_to_caller(const char *req_key, GVariant *result) +{ + GDBusMethodInvocation *invocation; + + invocation = (GDBusMethodInvocation *)g_hash_table_lookup(req_table, + (gpointer)req_key); + if (invocation == NULL) { + ERR("no such request id"); + return -1; + } + + g_dbus_method_invocation_return_value(invocation, result); + g_hash_table_remove(req_table, (gpointer)req_key); + + return 0; +} + static const GDBusInterfaceVTable interface_vtable = { __handle_method_call, @@ -598,11 +616,17 @@ int __init_request_handler(void) G_BUS_NAME_OWNER_FLAGS_NONE, __on_bus_acquired, __on_name_acquired, __on_name_lost, NULL, NULL); + req_table = g_hash_table_new_full(g_str_hash, g_str_equal, + free, NULL); + if (req_table == NULL) + return -1; + return 0; } void __fini_request_handler(void) { + g_hash_table_destroy(req_table); g_bus_unown_name(owner_id); g_dbus_node_info_unref(instropection_data); } -- 2.7.4 From ededacc7499c018973b71b0c40d9b9e877ee5092 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 26 Nov 2015 17:43:24 +0900 Subject: [PATCH 04/16] Add drm related methods ADDED: generate_license_request register_license decrypt_package Change-Id: Iaa8be0c19b6bfc6a90fc3b4028ea39e1f98f42b2 Signed-off-by: Sangyoon Jang --- CMakeLists.txt | 1 + include/pkgmgr-server.h | 3 + org.tizen.pkgmgr.conf.in | 3 + packaging/pkgmgr-server.spec | 1 + src/pkgmgr-server.c | 79 +++++++++++++++++++++++++ src/request.c | 134 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 221 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index acb751b..7accf56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ pkg_check_modules(SERVER_DEPS REQUIRED pkgmgr-parser pkgmgr-info libtzplatform-config + drm-service-core-tizen pkgmgr) FOREACH(SERVER_FLAGS ${SERVER_DEPS_CFLAGS}) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SERVER_FLAGS}") diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 6bdafe2..8ab7247 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -55,6 +55,9 @@ enum request_type { PKGMGR_REQUEST_TYPE_CLEARCACHE, PKGMGR_REQUEST_TYPE_KILL, PKGMGR_REQUEST_TYPE_CHECK, + PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST, + PKGMGR_REQUEST_TYPE_REGISTER_LICENSE, + PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE, }; typedef struct { diff --git a/org.tizen.pkgmgr.conf.in b/org.tizen.pkgmgr.conf.in index 266985f..20519d0 100644 --- a/org.tizen.pkgmgr.conf.in +++ b/org.tizen.pkgmgr.conf.in @@ -18,5 +18,8 @@ + + + diff --git a/packaging/pkgmgr-server.spec b/packaging/pkgmgr-server.spec index 80b7543..a881917 100644 --- a/packaging/pkgmgr-server.spec +++ b/packaging/pkgmgr-server.spec @@ -22,6 +22,7 @@ BuildRequires: pkgconfig(xdgmime) BuildRequires: pkgconfig(db-util) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(pkgmgr) +BuildRequires: pkgconfig(drm-service-core-tizen) BuildRequires: pkgmgr-info-parser-devel BuildRequires: pkgmgr-info-parser BuildRequires: fdupes diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index bc1b2c8..d515099 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "pkgmgr_installer.h" #include "pkgmgr-server.h" @@ -880,6 +881,75 @@ static void __process_check(pm_dbus_msg *item) pkgmgrinfo_pkginfo_destroy_pkginfo(handle); } +static void __process_generate_license_request(pm_dbus_msg *item) +{ + int ret; + char *resp_data; + char req_data[MAX_PKG_ARGS_LEN]; + unsigned int req_data_len; + char license_url[MAX_PKG_ARGS_LEN]; + unsigned int license_url_len; + + resp_data = item->args; + req_data_len = sizeof(req_data); + license_url_len = sizeof(license_url); + + ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data), + req_data, &req_data_len, license_url, &license_url_len); + if (ret != TADC_SUCCESS) { + ERR("drm_tizen_generate_license_request failed: %d", ret); + __return_value_to_caller(item->req_id, g_variant_new("(iss)", + PKGMGR_R_ESYSTEM, "", "")); + return; + } + + __return_value_to_caller(item->req_id, + g_variant_new("(iss)", PKGMGR_R_OK, req_data, + license_url)); +} + +static void __process_register_license(pm_dbus_msg *item) +{ + int ret; + char *resp_data; + + resp_data = item->args; + + ret = drm_tizen_register_license(resp_data, strlen(resp_data)); + if (ret != TADC_SUCCESS) { + ERR("drm_tizen_register_license failed: %d", ret); + __return_value_to_caller(item->req_id, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + return; + } + + __return_value_to_caller(item->req_id, + g_variant_new("(i)", PKGMGR_R_OK)); +} + +static void __process_decrypt_package(pm_dbus_msg *item) +{ + int ret; + char *drm_file_path; + char *decrypted_file_path; + + drm_file_path = item->pkgid; + decrypted_file_path = item->args; + + /* TODO: check ownership of decrypted file */ + ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path), + decrypted_file_path, strlen(decrypted_file_path)); + if (ret != TADC_SUCCESS) { + ERR("drm_tizen_register_license failed: %d", ret); + __return_value_to_caller(item->req_id, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + return; + } + + __return_value_to_caller(item->req_id, + g_variant_new("(i)", PKGMGR_R_OK)); +} + gboolean queue_job(void *data) { pm_dbus_msg *item = NULL; @@ -952,6 +1022,15 @@ gboolean queue_job(void *data) case PKGMGR_REQUEST_TYPE_CHECK: __process_check(item); break; + case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST: + __process_generate_license_request(item); + break; + case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE: + __process_register_license(item); + break; + case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE: + __process_decrypt_package(item); + break; } /* exit child */ _save_queue_status(item, "done"); diff --git a/src/request.c b/src/request.c index cbce8dd..0019428 100644 --- a/src/request.c +++ b/src/request.c @@ -90,6 +90,21 @@ static const char instropection_xml[] = " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " ""; static GDBusNodeInfo *instropection_data; @@ -489,6 +504,116 @@ static int __handle_request_check(uid_t uid, return 0; } +static int __handle_request_generate_license_request(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + char *reqkey; + char *resp_data = NULL; + + g_variant_get(parameters, "(&s)", &resp_data); + if (resp_data == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(iss)", PKGMGR_R_ECOMM, "", "")); + return -1; + } + + reqkey = __generate_reqkey("drm"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(iss)", PKGMGR_R_ENOMEM, "", + "")); + return -1; + } + + if (_pm_queue_push(uid, reqkey, + PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST, + "pkg", "", resp_data)) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(iss)", PKGMGR_R_ESYSTEM, "", + "")); + free(reqkey); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + +static int __handle_request_register_license(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + char *reqkey; + char *resp_data = NULL; + + g_variant_get(parameters, "(&s)", &resp_data); + if (resp_data == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ECOMM)); + return -1; + } + + reqkey = __generate_reqkey("drm"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ENOMEM)); + return -1; + } + + if (_pm_queue_push(uid, reqkey, PKGMGR_REQUEST_TYPE_REGISTER_LICENSE, + "pkg", "", resp_data)) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + free(reqkey); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + +static int __handle_request_decrypt_package(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + char *reqkey; + char *drm_file_path = NULL; + char *decrypted_file_path = NULL; + + g_variant_get(parameters, "(&s&s)", &drm_file_path, + &decrypted_file_path); + if (drm_file_path == NULL || decrypted_file_path == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ECOMM)); + return -1; + } + + reqkey = __generate_reqkey("drm"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ENOMEM)); + return -1; + } + + if (_pm_queue_push(uid, reqkey, PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE, + "pkg", drm_file_path, decrypted_file_path)) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + free(reqkey); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + static uid_t __get_caller_uid(GDBusConnection *connection, const char *name) { GError *err = NULL; @@ -547,6 +672,15 @@ static void __handle_method_call(GDBusConnection *connection, ret = __handle_request_kill(uid, invocation, parameters); else if (g_strcmp0(method_name, "check") == 0) ret = __handle_request_check(uid, invocation, parameters); + else if (g_strcmp0(method_name, "generate_license_request") == 0) + ret = __handle_request_generate_license_request(uid, invocation, + parameters); + else if (g_strcmp0(method_name, "register_license") == 0) + ret = __handle_request_register_license(uid, invocation, + parameters); + else if (g_strcmp0(method_name, "decrypt_package") == 0) + ret = __handle_request_decrypt_package(uid, invocation, + parameters); else ret = -1; -- 2.7.4 From 8fde4fd147e31d90108df166f51f10fd29308bd1 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Mon, 11 Jan 2016 09:13:26 +0900 Subject: [PATCH 05/16] Fix wrong filepath for kill/check command Change-Id: Ibb7d696be7f504f0420b384e797b9c5c9b665a32 Signed-off-by: Junghyun Yeon --- src/pkgmgr-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index d515099..0971777 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -483,7 +483,7 @@ static void __make_pid_info_file(char *req_key, int pid) if(req_key == NULL) return; - snprintf(info_file, PATH_MAX, "/tmp/%s", req_key); + snprintf(info_file, PATH_MAX, "/tmp/pkgmgr/%s", req_key); DBG("info_path(%s)", info_file); file = fopen(info_file, "w"); -- 2.7.4 From 88d88b7ac08080fbb30fcaeaab2d6ec0de2ab424 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Wed, 13 Jan 2016 17:20:24 +0900 Subject: [PATCH 06/16] Each user can disable global app separately Changes applied at [slp-pkgmgr][pkgmgr-info][pkgmgr-server] Change-Id: Iab92e323553ab6f58ef330ac9f7b1d37b0094293 Signed-off-by: Junghyun Yeon --- include/pkgmgr-server.h | 2 ++ src/pkgmgr-server.c | 16 +++++++++++ src/request.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 8ab7247..41f0ee8 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -53,6 +53,8 @@ enum request_type { PKGMGR_REQUEST_TYPE_GETSIZE, PKGMGR_REQUEST_TYPE_CLEARDATA, PKGMGR_REQUEST_TYPE_CLEARCACHE, + PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP, + PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP, PKGMGR_REQUEST_TYPE_KILL, PKGMGR_REQUEST_TYPE_CHECK, PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST, diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 0971777..67db3f7 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -802,6 +802,16 @@ static void __process_disable(pm_dbus_msg *item) /* TODO */ } +static void __process_enable_global_app(pm_dbus_msg *item) +{ + pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 0); +} + +static void __process_disable_global_app(pm_dbus_msg *item) +{ + pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 1); +} + static void __process_getsize(pm_dbus_msg *item) { char **args_vector; @@ -1016,6 +1026,12 @@ gboolean queue_job(void *data) case PKGMGR_REQUEST_TYPE_CLEARCACHE: __process_clearcache(item); break; + case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP: + __process_enable_global_app(item); + break; + case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP: + __process_disable_global_app(item); + break; case PKGMGR_REQUEST_TYPE_KILL: __process_kill(item); break; diff --git a/src/request.c b/src/request.c index 0019428..ca27a2e 100644 --- a/src/request.c +++ b/src/request.c @@ -62,6 +62,16 @@ static const char instropection_xml[] = " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " " " " " @@ -324,7 +334,7 @@ static int __handle_request_enable(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE, "pkg", + if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE, "none", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); @@ -350,7 +360,7 @@ static int __handle_request_disable(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE, "pkg", + if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE, "none", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); @@ -363,6 +373,58 @@ static int __handle_request_disable(uid_t uid, return 0; } +static int __handle_request_enable_global_app(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *appid = NULL; + + g_variant_get(parameters, "(u&s)", &target_uid, &appid); + if (target_uid == (uid_t)-1 || appid == 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_GLOBAL_APP, "none", + appid, "")) { + 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_global_app(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *appid = NULL; + + g_variant_get(parameters, "(u&s)", &target_uid, &appid); + if (target_uid == (uid_t)-1 || appid == 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_GLOBAL_APP, "none", + appid, "")) { + 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) { @@ -668,6 +730,10 @@ static void __handle_method_call(GDBusConnection *connection, 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, "enable_global_app") == 0) + ret = __handle_request_enable_global_app(uid, invocation, parameters); + else if (g_strcmp0(method_name, "disable_global_app") == 0) + ret = __handle_request_disable_global_app(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) -- 2.7.4 From c2f63f5a33790fde2b82681f602080c106dd6e82 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 27 Jan 2016 17:27:22 +0900 Subject: [PATCH 07/16] Fork child process for the backend installer only use g_spawn_async which calls fork() and execv() internally. Change-Id: Ibec6f0cd0a29ab2d3719ecb1d2af39905aaaf8d0 Signed-off-by: Sangyoon Jang --- src/pkgmgr-server.c | 362 ++++++++++++++++++++++++++++------------------------ 1 file changed, 192 insertions(+), 170 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 67db3f7..bf33188 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -654,6 +654,8 @@ static char **__generate_argv(const char *args) gint argcp; gchar **argvp; GError *gerr = NULL; + int i; + ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr); if (FALSE == ret_parse) { @@ -662,198 +664,220 @@ static char **__generate_argv(const char *args) 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]); - } + for (i = 0; i < argcp; i++) + DBG(">>>>>> argsv[%d]=%s", i, argvp[i]); - return args_vector; + return argvp; } -static void __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid) +void __set_environment(gpointer user_data) { - user_ctx* user_context = get_user_context(uid); + user_ctx *ctx = (user_ctx *)user_data; - 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); + if (set_environement(ctx)) + DBG("Failed to set env for the user : %d", ctx->uid); +} - /* Execute backend !!! */ +static int __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid) +{ + user_ctx* user_context; + GError *error = NULL; + gboolean ret; + int pid; - int ret = execv(cmd, argv); + user_context = get_user_context(uid); + if (!user_context) { + DBG("Failed to getenv for the user : %d", uid); + return -1; + } - /* Code below: exec failure. Should not be happened! */ - DBG(">>>>>> OOPS 2!!!"); + ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + __set_environment, (gpointer)user_context, &pid, + &error); + if (ret != TRUE) { + ERR("Failed to excute backend: %s", error->message); + g_error_free(error); + } - /* g_strfreev(args_vector); *//* FIXME: causes error */ + free_user_context(user_context); - if (ret == -1) { - perror("fail to exec"); - exit(1); - } + return pid; } -static void __process_install(pm_dbus_msg *item) +static int __process_install(pm_dbus_msg *item) { char *backend_cmd; - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN] = {'\0', }; + int pid; backend_cmd = _get_backend_cmd(item->pkg_type); if (backend_cmd == NULL) - return; + return -1; 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; + argv = __generate_argv(args); + + pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + g_strfreev(argv); + free(backend_cmd); - __exec_with_arg_vector(backend_cmd, args_vector, item->uid); + return pid; } -static void __process_reinstall(pm_dbus_msg *item) +static int __process_reinstall(pm_dbus_msg *item) { char *backend_cmd; - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; backend_cmd = _get_backend_cmd(item->pkg_type); if (backend_cmd == NULL) - return; + return -1; 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; + argv = __generate_argv(args); + + pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + + g_strfreev(argv); + free(backend_cmd); - __exec_with_arg_vector(backend_cmd, args_vector, item->uid); + return pid; } -static void __process_uninstall(pm_dbus_msg *item) +static int __process_uninstall(pm_dbus_msg *item) { char *backend_cmd; - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; backend_cmd = _get_backend_cmd(item->pkg_type); if (backend_cmd == NULL) - return; + return -1; 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; + argv = __generate_argv(args); + + pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); - __exec_with_arg_vector(backend_cmd, args_vector, item->uid); + g_strfreev(argv); + free(backend_cmd); + + return pid; } -static void __process_move(pm_dbus_msg *item) +static int __process_move(pm_dbus_msg *item) { char *backend_cmd; - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; backend_cmd = _get_backend_cmd(item->pkg_type); if (backend_cmd == NULL) - return; + return -1; /* 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; + argv = __generate_argv(args); + + pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); - __exec_with_arg_vector(backend_cmd, args_vector, item->uid); + g_strfreev(argv); + free(backend_cmd); + + return pid; } -static void __process_enable(pm_dbus_msg *item) +static int __process_enable(pm_dbus_msg *item) { /* TODO */ + return 0; } -static void __process_disable(pm_dbus_msg *item) +static int __process_disable(pm_dbus_msg *item) { /* TODO */ + return 0; } -static void __process_enable_global_app(pm_dbus_msg *item) +static int __process_enable_global_app(pm_dbus_msg *item) { pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 0); + return 0; } -static void __process_disable_global_app(pm_dbus_msg *item) +static int __process_disable_global_app(pm_dbus_msg *item) { pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 1); + return 0; } -static void __process_getsize(pm_dbus_msg *item) +static int __process_getsize(pm_dbus_msg *item) { - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; 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); + argv = __generate_argv(args); + pid = __exec_with_arg_vector("/usr/bin/pkg_getsize", argv, item->uid); + + g_strfreev(argv); + + return pid; } -static void __process_cleardata(pm_dbus_msg *item) +static int __process_cleardata(pm_dbus_msg *item) { char *backend_cmd; - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; backend_cmd = _get_backend_cmd(item->pkg_type); if (backend_cmd == NULL) - return; + return -1; /* 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; + argv = __generate_argv(args); + + pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + + g_strfreev(argv); + free(backend_cmd); - __exec_with_arg_vector(backend_cmd, args_vector, item->uid); + return pid; } -static void __process_clearcache(pm_dbus_msg *item) +static int __process_clearcache(pm_dbus_msg *item) { - char **args_vector; + char **argv; char args[MAX_PKG_ARGS_LEN]; + int pid; snprintf(args, sizeof(args), "%s", item->pkgid); - args_vector = __generate_argv(args); - __exec_with_arg_vector("/usr/bin/pkg_clearcache", args_vector, - item->uid); + argv = __generate_argv(args); + pid = __exec_with_arg_vector("/usr/bin/pkg_clearcache", argv, item->uid); + + g_strfreev(argv); + + return pid; } -static void __process_kill(pm_dbus_msg *item) +static int __process_kill(pm_dbus_msg *item) { int ret; pkgmgrinfo_pkginfo_h handle; @@ -862,17 +886,21 @@ static void __process_kill(pm_dbus_msg *item) &handle); if (ret < 0) { ERR("Failed to get handle"); - return; + return -1; } 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); + if (ret < 0) { + ERR("pkgmgrinfo_appinfo_get_list() failed"); + return -1; + } + + return 0; } -static void __process_check(pm_dbus_msg *item) +static int __process_check(pm_dbus_msg *item) { int ret; pkgmgrinfo_pkginfo_h handle; @@ -881,17 +909,21 @@ static void __process_check(pm_dbus_msg *item) &handle); if (ret < 0) { ERR("Failed to get handle"); - return; + return -1; } 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); + if (ret < 0) { + ERR("pkgmgrinfo_appinfo_get_list() failed"); + return -1; + } + + return 0; } -static void __process_generate_license_request(pm_dbus_msg *item) +static int __process_generate_license_request(pm_dbus_msg *item) { int ret; char *resp_data; @@ -910,15 +942,17 @@ static void __process_generate_license_request(pm_dbus_msg *item) ERR("drm_tizen_generate_license_request failed: %d", ret); __return_value_to_caller(item->req_id, g_variant_new("(iss)", PKGMGR_R_ESYSTEM, "", "")); - return; + return -1; } __return_value_to_caller(item->req_id, g_variant_new("(iss)", PKGMGR_R_OK, req_data, license_url)); + + return 0; } -static void __process_register_license(pm_dbus_msg *item) +static int __process_register_license(pm_dbus_msg *item) { int ret; char *resp_data; @@ -930,14 +964,16 @@ static void __process_register_license(pm_dbus_msg *item) ERR("drm_tizen_register_license failed: %d", ret); __return_value_to_caller(item->req_id, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); - return; + return -1; } __return_value_to_caller(item->req_id, g_variant_new("(i)", PKGMGR_R_OK)); + + return 0; } -static void __process_decrypt_package(pm_dbus_msg *item) +static int __process_decrypt_package(pm_dbus_msg *item) { int ret; char *drm_file_path; @@ -953,11 +989,13 @@ static void __process_decrypt_package(pm_dbus_msg *item) ERR("drm_tizen_register_license failed: %d", ret); __return_value_to_caller(item->req_id, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); - return; + return -1; } __return_value_to_caller(item->req_id, g_variant_new("(i)", PKGMGR_R_OK)); + + return 0; } gboolean queue_job(void *data) @@ -965,6 +1003,7 @@ gboolean queue_job(void *data) pm_dbus_msg *item = NULL; backend_info *ptr; int x; + int ret; /* Pop a job from queue */ for (x = 0, ptr = begin; x < num_of_backends; x++, ptr++) { @@ -984,85 +1023,68 @@ gboolean queue_job(void *data) __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_ENABLE_GLOBAL_APP: - __process_enable_global_app(item); - break; - case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP: - __process_disable_global_app(item); - break; - case PKGMGR_REQUEST_TYPE_KILL: - __process_kill(item); - break; - case PKGMGR_REQUEST_TYPE_CHECK: - __process_check(item); - break; - case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST: - __process_generate_license_request(item); - break; - case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE: - __process_register_license(item); - break; - case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE: - __process_decrypt_package(item); - break; - } - /* exit child */ - _save_queue_status(item, "done"); - exit(0); - break; - - case -1: - fprintf(stderr, "Fail to execute_fork()\n"); - exit(1); + DBG("handle request type [%d]", ptr->pid, item->req_type); - default: /* parent */ - DBG("parent exit\n"); - _save_queue_status(item, "done"); + switch (item->req_type) { + case PKGMGR_REQUEST_TYPE_INSTALL: + ret = __process_install(item); + break; + case PKGMGR_REQUEST_TYPE_REINSTALL: + ret = __process_reinstall(item); + break; + case PKGMGR_REQUEST_TYPE_UNINSTALL: + ret = __process_uninstall(item); + break; + case PKGMGR_REQUEST_TYPE_MOVE: + ret = __process_move(item); + break; + case PKGMGR_REQUEST_TYPE_ENABLE: + ret = __process_enable(item); + break; + case PKGMGR_REQUEST_TYPE_DISABLE: + ret = __process_disable(item); + break; + case PKGMGR_REQUEST_TYPE_GETSIZE: + ret = __process_getsize(item); + break; + case PKGMGR_REQUEST_TYPE_CLEARDATA: + ret = __process_cleardata(item); + break; + case PKGMGR_REQUEST_TYPE_CLEARCACHE: + ret = __process_clearcache(item); + break; + case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP: + ret = __process_enable_global_app(item); + break; + case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP: + ret = __process_disable_global_app(item); + break; + case PKGMGR_REQUEST_TYPE_KILL: + ret = __process_kill(item); + break; + case PKGMGR_REQUEST_TYPE_CHECK: + ret = __process_check(item); + break; + case PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST: + ret = __process_generate_license_request(item); + break; + case PKGMGR_REQUEST_TYPE_REGISTER_LICENSE: + ret = __process_register_license(item); + break; + case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE: + ret = __process_decrypt_package(item); + break; + default: + ret = -1; break; } + ptr->pid = ret; free(item); return FALSE; -- 2.7.4 From 90afa4547c510ee3dd141ddaba2cd7fdae1d7b96 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 28 Jan 2016 17:59:10 +0900 Subject: [PATCH 08/16] Set backend busy, recovery mode when needed only Change-Id: I1470c40051f47a58f2aa3fdb75d561262b237d88 Signed-off-by: Sangyoon Jang --- src/pkgmgr-server.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index bf33188..7af00fc 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -1020,9 +1020,6 @@ gboolean queue_job(void *data) if (x == num_of_backends) return FALSE; - __set_backend_busy(x); - __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); - /*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); @@ -1032,15 +1029,23 @@ gboolean queue_job(void *data) switch (item->req_type) { case PKGMGR_REQUEST_TYPE_INSTALL: + __set_backend_busy(x); + __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); ret = __process_install(item); break; case PKGMGR_REQUEST_TYPE_REINSTALL: + __set_backend_busy(x); + __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); ret = __process_reinstall(item); break; case PKGMGR_REQUEST_TYPE_UNINSTALL: + __set_backend_busy(x); + __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); ret = __process_uninstall(item); break; case PKGMGR_REQUEST_TYPE_MOVE: + __set_backend_busy(x); + __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); ret = __process_move(item); break; case PKGMGR_REQUEST_TYPE_ENABLE: @@ -1050,12 +1055,15 @@ gboolean queue_job(void *data) ret = __process_disable(item); break; case PKGMGR_REQUEST_TYPE_GETSIZE: + __set_backend_busy(x); ret = __process_getsize(item); break; case PKGMGR_REQUEST_TYPE_CLEARDATA: + __set_backend_busy(x); ret = __process_cleardata(item); break; case PKGMGR_REQUEST_TYPE_CLEARCACHE: + __set_backend_busy(x); ret = __process_clearcache(item); break; case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP: -- 2.7.4 From e89f376e5237f92c0edc32aafffc47d057b6d3cc Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 28 Jan 2016 15:41:55 +0900 Subject: [PATCH 09/16] Fix processing getsize, clearcache argv[0] should be excutable path. remove unused parameter of __exec_with_arg_vector. rename __exec_with_arg_vector to __fork_and_exec_with_args for clarify functionality. Change-Id: I8e2230fca1aeb563adf0705c99bd47d4f0362277 Signed-off-by: Sangyoon Jang --- src/pkgmgr-server.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 7af00fc..c49af50 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -679,7 +679,7 @@ void __set_environment(gpointer user_data) DBG("Failed to set env for the user : %d", ctx->uid); } -static int __exec_with_arg_vector(const char *cmd, char **argv, uid_t uid) +static int __fork_and_exec_with_args(char **argv, uid_t uid) { user_ctx* user_context; GError *error = NULL; @@ -721,7 +721,7 @@ static int __process_install(pm_dbus_msg *item) argv = __generate_argv(args); - pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); free(backend_cmd); @@ -743,7 +743,7 @@ static int __process_reinstall(pm_dbus_msg *item) item->req_id, item->pkgid); argv = __generate_argv(args); - pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); free(backend_cmd); @@ -766,7 +766,7 @@ static int __process_uninstall(pm_dbus_msg *item) item->req_id, item->pkgid); argv = __generate_argv(args); - pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); free(backend_cmd); @@ -790,7 +790,7 @@ static int __process_move(pm_dbus_msg *item) item->req_id, item->pkgid, item->args); argv = __generate_argv(args); - pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); free(backend_cmd); @@ -824,14 +824,15 @@ static int __process_disable_global_app(pm_dbus_msg *item) static int __process_getsize(pm_dbus_msg *item) { + static const char *backend_cmd = "/usr/bin/pkg_getsize"; char **argv; char args[MAX_PKG_ARGS_LEN]; int pid; - snprintf(args, sizeof(args), "%s %s -k %s", item->pkgid, item->args, - item->req_id); + snprintf(args, sizeof(args), "%s %s %s -k %s", backend_cmd, item->pkgid, + item->args, item->req_id); argv = __generate_argv(args); - pid = __exec_with_arg_vector("/usr/bin/pkg_getsize", argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); @@ -854,7 +855,7 @@ static int __process_cleardata(pm_dbus_msg *item) item->req_id, item->pkgid); argv = __generate_argv(args); - pid = __exec_with_arg_vector(backend_cmd, argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); free(backend_cmd); @@ -864,13 +865,14 @@ static int __process_cleardata(pm_dbus_msg *item) static int __process_clearcache(pm_dbus_msg *item) { + static const char *backend_cmd = "/usr/bin/pkg_clearcache"; char **argv; char args[MAX_PKG_ARGS_LEN]; int pid; - snprintf(args, sizeof(args), "%s", item->pkgid); + snprintf(args, sizeof(args), "%s %s", backend_cmd, item->pkgid); argv = __generate_argv(args); - pid = __exec_with_arg_vector("/usr/bin/pkg_clearcache", argv, item->uid); + pid = __fork_and_exec_with_args(argv, item->uid); g_strfreev(argv); -- 2.7.4 From 0db7e5662a4d39d324d8691431fdd03b6af5e766 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 21 Jan 2016 13:50:02 +0900 Subject: [PATCH 10/16] Add blacklist management feature Change-Id: I48543f21262825bd70a2508195ff4d6191233341 Signed-off-by: Sangyoon Jang --- CMakeLists.txt | 5 +- blacklist.sql | 8 ++ include/pkgmgr-server.h | 7 ++ org.tizen.pkgmgr.conf.in | 3 + packaging/pkgmgr-server.spec | 11 ++- src/db.c | 218 +++++++++++++++++++++++++++++++++++++++++++ src/pkgmgr-server.c | 46 +++++++++ src/request.c | 133 ++++++++++++++++++++++++++ 8 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 blacklist.sql create mode 100644 src/db.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7accf56..0bc54d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,13 +11,15 @@ SET(EXEC_PREFIX "\${prefix}") SET(LIBDIR ${LIB_INSTALL_DIR}) SET(INCLUDEDIR "\${prefix}/include") +ADD_DEFINITIONS(-DDB_DIR="${DB_DIR}") + 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) +SET(SRCS src/pkgmgr-server.c src/request.c src/pm-queue.c src/db.c) pkg_check_modules(SERVER_DEPS REQUIRED gio-2.0 @@ -26,6 +28,7 @@ pkg_check_modules(SERVER_DEPS REQUIRED pkgmgr-info libtzplatform-config drm-service-core-tizen + sqlite3 pkgmgr) FOREACH(SERVER_FLAGS ${SERVER_DEPS_CFLAGS}) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SERVER_FLAGS}") diff --git a/blacklist.sql b/blacklist.sql new file mode 100644 index 0000000..0db3ddb --- /dev/null +++ b/blacklist.sql @@ -0,0 +1,8 @@ +PRAGMA user_version = 30; /* Tizen 3.0 */ +PRAGMA journal_mode = WAL; + +CREATE TABLE blacklist ( + uid INTEGER NOT NULL, + pkgid TEXT NOT NULL, + UNIQUE (uid, pkgid) +); diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 41f0ee8..3b0c874 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -23,6 +23,7 @@ #ifndef _PKGMGR_SERVER_H_ #define _PKGMGR_SERVER_H_ +#include #include #ifdef LOG_TAG @@ -60,6 +61,9 @@ enum request_type { PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST, PKGMGR_REQUEST_TYPE_REGISTER_LICENSE, PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE, + PKGMGR_REQUEST_TYPE_ADD_BLACKLIST, + PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST, + PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST, }; typedef struct { @@ -85,5 +89,8 @@ gboolean queue_job(void *data); int __return_value_to_caller(const char *req_key, GVariant *result); int __init_request_handler(void); void __fini_request_handler(void); +int __add_blacklist(uid_t uid, const char *pkgid); +int __remove_blacklist(uid_t uid, const char *pkgid); +int __check_blacklist(uid_t uid, const char *pkgid, int *result); #endif/* _PKGMGR_SERVER_H_ */ diff --git a/org.tizen.pkgmgr.conf.in b/org.tizen.pkgmgr.conf.in index 20519d0..c237b44 100644 --- a/org.tizen.pkgmgr.conf.in +++ b/org.tizen.pkgmgr.conf.in @@ -21,5 +21,8 @@ + + + diff --git a/packaging/pkgmgr-server.spec b/packaging/pkgmgr-server.spec index a881917..80cd390 100644 --- a/packaging/pkgmgr-server.spec +++ b/packaging/pkgmgr-server.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(db-util) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(drm-service-core-tizen) +BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgmgr-info-parser-devel BuildRequires: pkgmgr-info-parser BuildRequires: fdupes @@ -34,8 +35,12 @@ Packager Manager server package for packaging %setup -q cp %{SOURCE1001} . +%define db_dir %{_localstatedir}/lib/package-manager + %build -%cmake . +sqlite3 blacklist.db < ./blacklist.sql + +%cmake . -DDB_DIR=%{db_dir} %__make %{?_smp_mflags} @@ -46,6 +51,9 @@ mkdir -p %{buildroot}/usr/share/license cp LICENSE %{buildroot}/usr/share/license/%{name} mkdir -p %{buildroot}%{_sysconfdir}/package-manager/server +mkdir -p %{buildroot}%{db_dir} +install -m 0600 blacklist.db %{buildroot}%{db_dir} + %fdupes %{buildroot} %post @@ -58,5 +66,6 @@ mkdir -p %{buildroot}%{_sysconfdir}/package-manager/server %config %{_sysconfdir}/dbus-1/system.d/org.tizen.pkgmgr.conf %{_bindir}/pkgmgr-server %{_sysconfdir}/package-manager/server +%config(noreplace) %{db_dir}/blacklist.db %exclude %{_sysconfdir}/package-manager/server/queue_status /usr/share/license/%{name} diff --git a/src/db.c b/src/db.c new file mode 100644 index 0000000..c57f995 --- /dev/null +++ b/src/db.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "pkgmgr-server.h" + +#ifndef DB_DIR +#define DB_DIR "/var/lib/package-manager" +#endif + +static const char *_get_db_path(void) +{ + return DB_DIR"/blacklist.db"; +} + +static sqlite3 *_open_db(void) +{ + int ret; + const char *path; + sqlite3 *db; + + path = _get_db_path(); + if (path == NULL) { + ERR("get db path error"); + return NULL; + } + + ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL); + if (ret != SQLITE_OK) { + ERR("open db error: %d", ret); + return NULL; + } + + return db; +} + +static int __add_blacklist_info(sqlite3 *db, uid_t uid, const char *pkgid) +{ + static const char query[] = + "INSERT INTO blacklist (uid, pkgid) VALUES(?, ?)"; + int ret; + sqlite3_stmt *stmt; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + ERR("prepare error: %s", sqlite3_errmsg(db)); + return -1; + } + + sqlite3_bind_int(stmt, 1, uid); + sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_STATIC); + + ret = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (ret != SQLITE_DONE) { + ERR("step error: %s", sqlite3_errmsg(db)); + return -1; + } + + return 0; +} + +int __add_blacklist(uid_t uid, const char *pkgid) +{ + int ret; + sqlite3 *db; + + db = _open_db(); + if (db == NULL) + return PKGMGR_R_ERROR; + + ret = sqlite3_exec(db, "BEGIN EXCLUSIVE", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + sqlite3_close_v2(db); + ERR("transaction failed"); + return PKGMGR_R_ERROR; + } + + if (__add_blacklist_info(db, uid, pkgid)) { + sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + sqlite3_close_v2(db); + return PKGMGR_R_ERROR; + } + + ret = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + ERR("commit error: %s", sqlite3_errmsg(db)); + sqlite3_close_v2(db); + return PKGMGR_R_ERROR; + } + + sqlite3_close_v2(db); + + return PKGMGR_R_OK; +} + +static int __remove_blacklist_info(sqlite3 *db, uid_t uid, const char *pkgid) +{ + static const char query[] = + "DELETE FROM blacklist WHERE uid=? AND pkgid=?"; + int ret; + sqlite3_stmt *stmt; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + ERR("prepare error: %s", sqlite3_errmsg(db)); + return -1; + } + + sqlite3_bind_int(stmt, 1, uid); + sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_STATIC); + + ret = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (ret != SQLITE_DONE) { + ERR("step error: %s", sqlite3_errmsg(db)); + return -1; + } + + return 0; +} + +int __remove_blacklist(uid_t uid, const char *pkgid) +{ + int ret; + sqlite3 *db; + + db = _open_db(); + if (db == NULL) + return PKGMGR_R_ERROR; + + ret = sqlite3_exec(db, "BEGIN EXCLUSIVE", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + sqlite3_close_v2(db); + ERR("transaction failed"); + return PKGMGR_R_ERROR; + } + + if (__remove_blacklist_info(db, uid, pkgid)) { + sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + sqlite3_close_v2(db); + return PKGMGR_R_ERROR; + } + + ret = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); + if (ret != SQLITE_OK) { + ERR("commit error: %s", sqlite3_errmsg(db)); + sqlite3_close_v2(db); + return PKGMGR_R_ERROR; + } + + sqlite3_close_v2(db); + + return PKGMGR_R_OK; +} + +int __check_blacklist(uid_t uid, const char *pkgid, int *result) +{ + static const char query[] = + "SELECT * FROM blacklist WHERE uid=? AND pkgid=?"; + int ret; + sqlite3 *db; + sqlite3_stmt *stmt; + + db = _open_db(); + if (db == NULL) { + *result = 0; + return PKGMGR_R_ERROR; + } + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + ERR("prepare error: %s", sqlite3_errmsg(db)); + *result = 0; + sqlite3_close_v2(db); + return PKGMGR_R_ERROR; + } + + sqlite3_bind_int(stmt, 1, uid); + sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_STATIC); + + ret = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (ret != SQLITE_ROW) { + if (ret != SQLITE_DONE) + ERR("step error: %s", sqlite3_errmsg(db)); + *result = 0; + sqlite3_close_v2(db); + return ret == SQLITE_DONE ? PKGMGR_R_OK : PKGMGR_R_ERROR; + } + + *result = 1; + sqlite3_close_v2(db); + + return PKGMGR_R_OK; +} diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index c49af50..1cf0ef5 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -1000,6 +1000,43 @@ static int __process_decrypt_package(pm_dbus_msg *item) return 0; } +static int __process_add_blacklist(pm_dbus_msg *item) +{ + int ret; + + ret = __add_blacklist(item->uid, item->pkgid); + + __return_value_to_caller(item->req_id, + g_variant_new("(i)", ret)); + + return ret; +} + +static int __process_remove_blacklist(pm_dbus_msg *item) +{ + int ret; + + ret = __remove_blacklist(item->uid, item->pkgid); + + __return_value_to_caller(item->req_id, + g_variant_new("(i)", ret)); + + return ret; +} + +static int __process_check_blacklist(pm_dbus_msg *item) +{ + int ret; + int result = 0; + + ret = __check_blacklist(item->uid, item->pkgid, &result); + + __return_value_to_caller(item->req_id, + g_variant_new("(ii)", result, ret)); + + return ret; +} + gboolean queue_job(void *data) { pm_dbus_msg *item = NULL; @@ -1089,6 +1126,15 @@ gboolean queue_job(void *data) case PKGMGR_REQUEST_TYPE_DECRYPT_PACKAGE: ret = __process_decrypt_package(item); break; + case PKGMGR_REQUEST_TYPE_ADD_BLACKLIST: + ret = __process_add_blacklist(item); + break; + case PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST: + ret = __process_remove_blacklist(item); + break; + case PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST: + ret = __process_check_blacklist(item); + break; default: ret = -1; break; diff --git a/src/request.c b/src/request.c index ca27a2e..ba79911 100644 --- a/src/request.c +++ b/src/request.c @@ -115,6 +115,22 @@ static const char instropection_xml[] = " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " ""; static GDBusNodeInfo *instropection_data; @@ -676,6 +692,114 @@ static int __handle_request_decrypt_package(uid_t uid, return 0; } +static int __handle_request_add_blacklist(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *reqkey; + 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; + } + + reqkey = __generate_reqkey("blacklist"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ENOMEM)); + return -1; + } + + if (_pm_queue_push(target_uid, reqkey, + PKGMGR_REQUEST_TYPE_ADD_BLACKLIST, + "pkg", pkgid, "")) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + +static int __handle_request_remove_blacklist(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *reqkey; + 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; + } + + reqkey = __generate_reqkey("blacklist"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ENOMEM)); + return -1; + } + + if (_pm_queue_push(target_uid, reqkey, + PKGMGR_REQUEST_TYPE_REMOVE_BLACKLIST, + "pkg", pkgid, "")) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + +static int __handle_request_check_blacklist(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *reqkey; + 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; + } + + reqkey = __generate_reqkey("blacklist"); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ENOMEM)); + return -1; + } + + if (_pm_queue_push(target_uid, reqkey, + PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST, + "pkg", pkgid, "")) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + static uid_t __get_caller_uid(GDBusConnection *connection, const char *name) { GError *err = NULL; @@ -747,6 +871,15 @@ static void __handle_method_call(GDBusConnection *connection, else if (g_strcmp0(method_name, "decrypt_package") == 0) ret = __handle_request_decrypt_package(uid, invocation, parameters); + else if (g_strcmp0(method_name, "add_blacklist") == 0) + ret = __handle_request_add_blacklist(uid, invocation, + parameters); + else if (g_strcmp0(method_name, "remove_blacklist") == 0) + ret = __handle_request_remove_blacklist(uid, invocation, + parameters); + else if (g_strcmp0(method_name, "check_blacklist") == 0) + ret = __handle_request_check_blacklist(uid, invocation, + parameters); else ret = -1; -- 2.7.4 From 81356499dbdc2a31c9ca777d2d2cf5e293458b81 Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 28 Jan 2016 19:58:20 +0900 Subject: [PATCH 11/16] Implement app signal related with app disable/enable Changes applied at [pkgmgr-tool][pkgmgr-info][slp-pkgmgr][pkgmgr-server] Change-Id: I66521744e30a20da8c67135cef16da92dea2d41c Signed-off-by: Junghyun Yeon --- include/pkgmgr-server.h | 11 ++-- src/pkgmgr-server.c | 162 ++++++++++++++++++++++++++++++++++++++++++----- src/request.c | 164 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 295 insertions(+), 42 deletions(-) diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 3b0c874..d4cadde 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -49,13 +49,15 @@ enum request_type { PKGMGR_REQUEST_TYPE_REINSTALL, PKGMGR_REQUEST_TYPE_UNINSTALL, PKGMGR_REQUEST_TYPE_MOVE, - PKGMGR_REQUEST_TYPE_ENABLE, - PKGMGR_REQUEST_TYPE_DISABLE, + PKGMGR_REQUEST_TYPE_ENABLE_PKG, + PKGMGR_REQUEST_TYPE_DISABLE_PKG, + PKGMGR_REQUEST_TYPE_ENABLE_APP, + PKGMGR_REQUEST_TYPE_DISABLE_APP, PKGMGR_REQUEST_TYPE_GETSIZE, PKGMGR_REQUEST_TYPE_CLEARDATA, PKGMGR_REQUEST_TYPE_CLEARCACHE, - PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP, - PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP, + PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID, + PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID, PKGMGR_REQUEST_TYPE_KILL, PKGMGR_REQUEST_TYPE_CHECK, PKGMGR_REQUEST_TYPE_GENERATE_LICENSE_REQUEST, @@ -72,6 +74,7 @@ typedef struct { uid_t uid; char pkg_type[MAX_PKG_TYPE_LEN]; char pkgid[MAX_PKG_NAME_LEN]; + char appid[MAX_PKG_NAME_LEN]; char args[MAX_PKG_ARGS_LEN]; } pm_dbus_msg; diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 1cf0ef5..230862a 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -203,6 +203,30 @@ static void __unset_recovery_mode(uid_t uid, char *pkgid, char *pkg_type) DBG("remove recovery_file[%s] fail\n", recovery_file); } +static void __send_app_signal(uid_t uid, const char *req_id, + const char *pkg_type, const char *pkgid, const char *appid, + const char *key, const char *val) +{ + pkgmgr_installer *pi; + + pi = pkgmgr_installer_new(); + if (!pi) { + DBG("Failure in creating the pkgmgr_installer object"); + return; + } + + if (pkgmgr_installer_set_request_type(pi,PKGMGR_REQ_ENABLE_DISABLE_APP)) + goto catch; + if (pkgmgr_installer_set_session_id(pi, req_id)) + goto catch; + pkgmgr_installer_send_app_signal(pi, pkg_type, pkgid, appid, key, val); + +catch: + pkgmgr_installer_free(pi); + + return; +} + static void send_fail_signal(char *pname, char *ptype, char *args) { DBG("send_fail_signal start\n"); @@ -705,6 +729,29 @@ static int __fork_and_exec_with_args(char **argv, uid_t uid) return pid; } +void __change_item_info(pm_dbus_msg *item, uid_t uid) +{ + int ret = 0; + char *pkgid = NULL; + pkgmgrinfo_appinfo_h handle = NULL; + + ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle); + if (ret != PMINFO_R_OK) + return; + + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(handle); + return; + } + + strncpy(item->appid, item->pkgid, sizeof(item->pkgid) - 1); + memset((item->pkgid),0,MAX_PKG_NAME_LEN); + strncpy(item->pkgid, pkgid, sizeof(item->pkgid) - 1); + + pkgmgrinfo_appinfo_destroy_appinfo(handle); +} + static int __process_install(pm_dbus_msg *item) { char *backend_cmd; @@ -798,28 +845,104 @@ static int __process_move(pm_dbus_msg *item) return pid; } -static int __process_enable(pm_dbus_msg *item) +static int __process_enable_pkg(pm_dbus_msg *item) { /* TODO */ return 0; } -static int __process_disable(pm_dbus_msg *item) +static int __process_disable_pkg(pm_dbus_msg *item) { /* TODO */ return 0; } -static int __process_enable_global_app(pm_dbus_msg *item) +static int __process_enable_app(pm_dbus_msg *item) { - pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 0); - return 0; + int ret = -1; + + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "start", "enable_app"); + + /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */ + __change_item_info(item, item->uid); + if (strlen(item->appid) == 0) { + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "end", "fail"); + return ret; + } + + ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 0); + if (ret != PMINFO_R_OK) + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "fail"); + else + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "ok"); + + return ret; } -static int __process_disable_global_app(pm_dbus_msg *item) +static int __process_disable_app(pm_dbus_msg *item) { - pkgmgr_parser_update_global_app_disable_info_in_db(item->pkgid, item->uid, 1); - return 0; + int ret = -1; + + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "start", "disable_app"); + + /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */ + __change_item_info(item, item->uid); + if (strlen(item->appid) == 0) { + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "end", "fail"); + return ret; + } + + ret = pkgmgr_parser_update_app_disable_info_in_usr_db(item->appid, item->uid, 1); + if (ret != PMINFO_R_OK) + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "fail"); + else + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "ok"); + + return ret; +} + +static int __process_enable_global_app_for_uid(pm_dbus_msg *item) +{ + int ret = -1; + + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "start", "enable_global_app_for_uid"); + + /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */ + __change_item_info(item, GLOBAL_USER); + if (strlen(item->appid) == 0) { + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "end", "fail"); + return ret; + } + + ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 0); + if (ret != PMINFO_R_OK) + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "fail"); + else + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "ok"); + + return ret; +} + +static int __process_disable_global_app_for_uid(pm_dbus_msg *item) +{ + int ret = -1; + + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "start", "disable_global_app_for_uid"); + + /* get actual pkgid and replace it to appid which is currently stored at pkgid variable */ + __change_item_info(item, GLOBAL_USER); + if (strlen(item->appid) == 0) { + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->pkgid, "end", "fail"); + return ret; + } + + ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(item->appid, item->uid, 1); + if (ret != PMINFO_R_OK) + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "fail"); + else + __send_app_signal(item->uid, item->req_id, item->pkg_type, item->pkgid, item->appid, "end", "ok"); + + return ret; } static int __process_getsize(pm_dbus_msg *item) @@ -1063,6 +1186,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); + memset((item->appid),0,MAX_PKG_NAME_LEN); ptr->uid = item->uid; DBG("handle request type [%d]", ptr->pid, item->req_type); @@ -1087,11 +1211,17 @@ gboolean queue_job(void *data) __set_recovery_mode(item->uid, item->pkgid, item->pkg_type); ret = __process_move(item); break; - case PKGMGR_REQUEST_TYPE_ENABLE: - ret = __process_enable(item); + case PKGMGR_REQUEST_TYPE_ENABLE_PKG: + ret = __process_enable_pkg(item); + break; + case PKGMGR_REQUEST_TYPE_DISABLE_PKG: + ret = __process_disable_pkg(item); + break; + case PKGMGR_REQUEST_TYPE_ENABLE_APP: + ret = __process_enable_app(item); break; - case PKGMGR_REQUEST_TYPE_DISABLE: - ret = __process_disable(item); + case PKGMGR_REQUEST_TYPE_DISABLE_APP: + ret = __process_disable_app(item); break; case PKGMGR_REQUEST_TYPE_GETSIZE: __set_backend_busy(x); @@ -1105,11 +1235,11 @@ gboolean queue_job(void *data) __set_backend_busy(x); ret = __process_clearcache(item); break; - case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP: - ret = __process_enable_global_app(item); + case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID: + ret = __process_enable_global_app_for_uid(item); break; - case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP: - ret = __process_disable_global_app(item); + case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID: + ret = __process_disable_global_app_for_uid(item); break; case PKGMGR_REQUEST_TYPE_KILL: ret = __process_kill(item); diff --git a/src/request.c b/src/request.c index ba79911..8968807 100644 --- a/src/request.c +++ b/src/request.c @@ -56,21 +56,25 @@ static const char instropection_xml[] = " " " " " " + " " " " " " " " " " " " + " " " " - " " + " " " " " " " " + " " " " - " " + " " " " " " " " + " " " " " " " " @@ -337,7 +341,7 @@ static int __handle_request_move(uid_t uid, return 0; } -static int __handle_request_enable(uid_t uid, +static int __handle_request_enable_pkg(uid_t uid, GDBusMethodInvocation *invocation, GVariant *parameters) { uid_t target_uid = (uid_t)-1; @@ -350,7 +354,7 @@ static int __handle_request_enable(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE, "none", + if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE_PKG, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); @@ -363,7 +367,7 @@ static int __handle_request_enable(uid_t uid, return 0; } -static int __handle_request_disable(uid_t uid, +static int __handle_request_disable_pkg(uid_t uid, GDBusMethodInvocation *invocation, GVariant *parameters) { uid_t target_uid = (uid_t)-1; @@ -376,7 +380,7 @@ static int __handle_request_disable(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE, "none", + if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE_PKG, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); @@ -389,11 +393,13 @@ static int __handle_request_disable(uid_t uid, return 0; } -static int __handle_request_enable_global_app(uid_t uid, +static int __handle_request_enable_app(uid_t uid, GDBusMethodInvocation *invocation, GVariant *parameters) { uid_t target_uid = (uid_t)-1; char *appid = NULL; + char *reqkey = NULL; + int ret = -1; g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { @@ -402,24 +408,80 @@ static int __handle_request_enable_global_app(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP, "none", + reqkey = __generate_reqkey(appid); + if (reqkey == NULL) { + ret = -1; + goto catch; + } + + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_ENABLE_APP, "app", appid, "")) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); + ret = -1; + goto catch; + } + + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_OK, reqkey)); + + ret = 0; + +catch: + if(reqkey) + free(reqkey); + + return ret; +} + +static int __handle_request_disable_app(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *appid = NULL; + char *reqkey = NULL; + int ret = -1; + + g_variant_get(parameters, "(u&s)", &target_uid, &appid); + if (target_uid == (uid_t)-1 || appid == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ECOMM)); return -1; } + reqkey = __generate_reqkey(appid); + if (reqkey == NULL) { + ret = -1; + goto catch; + } + + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_DISABLE_APP, "app", + appid, "")) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); + ret = -1; + goto catch; + } + g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_OK)); + g_variant_new("(is)", PKGMGR_R_OK, reqkey)); - return 0; + ret = 0; + +catch: + if (reqkey) + free(reqkey); + + return ret; } -static int __handle_request_disable_global_app(uid_t uid, +static int __handle_request_enable_global_app_for_uid(uid_t uid, GDBusMethodInvocation *invocation, GVariant *parameters) { uid_t target_uid = (uid_t)-1; char *appid = NULL; + char *reqkey = NULL; + int ret = -1; g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { @@ -428,17 +490,71 @@ static int __handle_request_disable_global_app(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP, "none", + reqkey = __generate_reqkey(appid); + if (reqkey == NULL) { + ret = -1; + goto catch; + } + + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID, "app", appid, "")) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); + ret = -1; + goto catch; + } + + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_OK, reqkey)); + + ret = 0; + +catch: + if (reqkey) + free(reqkey); + + return ret; +} + +static int __handle_request_disable_global_app_for_uid(uid_t uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *appid = NULL; + char *reqkey = NULL; + int ret = -1; + + g_variant_get(parameters, "(u&s)", &target_uid, &appid); + if (target_uid == (uid_t)-1 || appid == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", PKGMGR_R_ECOMM)); return -1; } + reqkey = __generate_reqkey(appid); + if (reqkey == NULL) { + ret = -1; + goto catch; + } + + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID, "app", + appid, "")) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); + ret = -1; + goto catch; + } + g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_OK)); + g_variant_new("(is)", PKGMGR_R_OK, reqkey)); - return 0; + ret = 0; + +catch: + if (reqkey) + free(reqkey); + + return ret; } static int __handle_request_getsize(uid_t uid, @@ -847,17 +963,21 @@ static void __handle_method_call(GDBusConnection *connection, 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); + ret = __handle_request_enable_pkg(uid, invocation, parameters); else if (g_strcmp0(method_name, "disable") == 0) - ret = __handle_request_disable(uid, invocation, parameters); + ret = __handle_request_disable_pkg(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, "enable_global_app") == 0) - ret = __handle_request_enable_global_app(uid, invocation, parameters); - else if (g_strcmp0(method_name, "disable_global_app") == 0) - ret = __handle_request_disable_global_app(uid, invocation, parameters); + else if (g_strcmp0(method_name, "enable_app") == 0) + ret = __handle_request_enable_app(uid, invocation, parameters); + else if (g_strcmp0(method_name, "disable_app") == 0) + ret = __handle_request_disable_app(uid, invocation, parameters); + else if (g_strcmp0(method_name, "enable_global_app_for_uid") == 0) + ret = __handle_request_enable_global_app_for_uid(uid, invocation, parameters); + else if (g_strcmp0(method_name, "disable_global_app_for_uid") == 0) + ret = __handle_request_disable_global_app_for_uid(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) -- 2.7.4 From f9803630f7c33486924def60a8fa67b1a43a73e1 Mon Sep 17 00:00:00 2001 From: Tomasz Iwanek Date: Thu, 28 Jan 2016 14:43:40 +0100 Subject: [PATCH 12/16] Generate request key for cleardata request Fixes the problem that backend is called with missing key. backend -k -c $pkgid should be: backend -k $key -c $pkgid as pkgmgr_installer option parser requires key. Change-Id: Ie616e3b928f52c0e5ce2c1f6fa738ebd47af13fb --- src/request.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/request.c b/src/request.c index 8968807..ba202b2 100644 --- a/src/request.c +++ b/src/request.c @@ -599,6 +599,7 @@ static int __handle_request_cleardata(uid_t uid, uid_t target_uid = (uid_t)-1; char *pkgtype = NULL; char *pkgid = NULL; + char *reqkey = NULL; g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid); if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) { @@ -607,7 +608,11 @@ static int __handle_request_cleardata(uid_t uid, return -1; } - if (_pm_queue_push(target_uid, "", PKGMGR_REQUEST_TYPE_CLEARDATA, pkgtype, + reqkey = __generate_reqkey(pkgid); + if (reqkey == NULL) + return -1; + + if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_CLEARDATA, pkgtype, pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); -- 2.7.4 From ae9597dcbf9af27e67b43549333a97037eae37fb Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Thu, 18 Feb 2016 08:39:02 +0900 Subject: [PATCH 13/16] fix change_info to get pkg info properly Change-Id: I2c2869f2703c664835654da36062c562bbf16b01 Signed-off-by: Junghyun Yeon --- src/pkgmgr-server.c | 18 ++++++++++++++++-- src/request.c | 8 ++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index 230862a..d0dfa91 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -735,7 +735,21 @@ void __change_item_info(pm_dbus_msg *item, uid_t uid) char *pkgid = NULL; pkgmgrinfo_appinfo_h handle = NULL; - ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle); + switch (item->req_type) { + case PKGMGR_REQUEST_TYPE_DISABLE_APP: + case PKGMGR_REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID: + ret = pkgmgrinfo_appinfo_get_usr_appinfo(item->pkgid, uid, &handle); + break; + + case PKGMGR_REQUEST_TYPE_ENABLE_APP: + case PKGMGR_REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID: + ret = pkgmgrinfo_appinfo_get_usr_disabled_appinfo(item->pkgid, uid, &handle); + break; + + default: + return; + } + if (ret != PMINFO_R_OK) return; @@ -1188,7 +1202,7 @@ gboolean queue_job(void *data) strncpy(ptr->args, item->args, MAX_PKG_ARGS_LEN-1); memset((item->appid),0,MAX_PKG_NAME_LEN); ptr->uid = item->uid; - DBG("handle request type [%d]", ptr->pid, item->req_type); + DBG("handle request type [%d]", item->req_type); switch (item->req_type) { case PKGMGR_REQUEST_TYPE_INSTALL: diff --git a/src/request.c b/src/request.c index ba202b2..e1ed522 100644 --- a/src/request.c +++ b/src/request.c @@ -404,7 +404,7 @@ static int __handle_request_enable_app(uid_t uid, g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ECOMM)); + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); return -1; } @@ -445,7 +445,7 @@ static int __handle_request_disable_app(uid_t uid, g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ECOMM)); + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); return -1; } @@ -486,7 +486,7 @@ static int __handle_request_enable_global_app_for_uid(uid_t uid, g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ECOMM)); + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); return -1; } @@ -527,7 +527,7 @@ static int __handle_request_disable_global_app_for_uid(uid_t uid, g_variant_get(parameters, "(u&s)", &target_uid, &appid); if (target_uid == (uid_t)-1 || appid == NULL) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ECOMM)); + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); return -1; } -- 2.7.4 From 61017eec4c38edf165c4a17dcfcdda66de1a573c Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Fri, 26 Feb 2016 17:24:22 +0900 Subject: [PATCH 14/16] Remove hardcoded path Use _sysconfdir, fix incorrect comment. Change-Id: I241c76601efce425a651c59134ffd6e1f886cbf7 Signed-off-by: Sangyoon Jang --- CMakeLists.txt | 1 + packaging/pkgmgr-server.spec | 3 ++- src/pm-queue.c | 13 +++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bc54d6..8ab31aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ SET(LIBDIR ${LIB_INSTALL_DIR}) SET(INCLUDEDIR "\${prefix}/include") ADD_DEFINITIONS(-DDB_DIR="${DB_DIR}") +ADD_DEFINITIONS(-DBACKEND_DIR="${BACKEND_DIR}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -g -Wall") diff --git a/packaging/pkgmgr-server.spec b/packaging/pkgmgr-server.spec index 80cd390..21fe2fc 100644 --- a/packaging/pkgmgr-server.spec +++ b/packaging/pkgmgr-server.spec @@ -36,11 +36,12 @@ Packager Manager server package for packaging cp %{SOURCE1001} . %define db_dir %{_localstatedir}/lib/package-manager +%define backend_dir %{_sysconfdir}/package-manager/backend %build sqlite3 blacklist.db < ./blacklist.sql -%cmake . -DDB_DIR=%{db_dir} +%cmake . -DDB_DIR=%{db_dir} -DBACKEND_DIR=%{backend_dir} %__make %{?_smp_mflags} diff --git a/src/pm-queue.c b/src/pm-queue.c index 0100a9d..1839d53 100644 --- a/src/pm-queue.c +++ b/src/pm-queue.c @@ -31,7 +31,9 @@ #include "pkgmgr-server.h" #include "pm-queue.h" -#define BACKEND_INFO_DIR "/etc/package-manager/backend" +#ifndef BACKEND_DIR +#define BACKEND_DIR "/etc/package-manager/backend" +#endif static pm_queue_data *__get_head_from_pkgtype(const char *pkg_type); static void __update_head_from_pkgtype(pm_queue_data *data); @@ -149,22 +151,21 @@ int _pm_queue_init(void) 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); + n = scandir(BACKEND_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.*/ + The 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); + BACKEND_DIR, namelist[n]->d_name); if (lstat(abs_filename, &fileinfo)) { perror("lstat"); continue; @@ -194,7 +195,7 @@ int _pm_queue_init(void) !strcmp(namelist[n]->d_name, "..")) continue; snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s", - BACKEND_INFO_DIR, namelist[n]->d_name); + BACKEND_DIR, namelist[n]->d_name); if (lstat(abs_filename, &fileinfo) < 0) { perror(abs_filename); return -1; -- 2.7.4 From 15ad525b7e2e23beddefd749314b74de96206b5f Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 3 Mar 2016 15:57:21 +0900 Subject: [PATCH 15/16] Fix memory leak, insecure code - Free reqkey when failed. - Use snprintf instead of sprintf. Change-Id: Ia50c2dd0bb602d1ccbd773a8275cf072aec9d027 Signed-off-by: Sangyoon Jang --- src/pkgmgr-server.c | 25 ++++++++++++------------- src/request.c | 10 ++++------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index d0dfa91..e80b463 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -599,7 +599,7 @@ int set_environement(user_ctx *ctx) return res; } -user_ctx* get_user_context(uid_t uid) +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 @@ -608,9 +608,10 @@ user_ctx* get_user_context(uid_t uid) */ user_ctx *context_res; char **env = NULL; - struct passwd * pwd; + struct passwd *pwd; int len; int ret = 0; + int i; pwd = getpwuid(uid); if (!pwd) @@ -622,34 +623,33 @@ user_ctx* get_user_context(uid_t uid) ret = -1; break; } - env = (char**)malloc(3* sizeof(char *)); + 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)); + 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)); + snprintf(env[0], len + 1, "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); + snprintf(env[1], len + 1, "USER=%s", pwd->pw_name); env[2] = NULL; } while (0); if (ret == -1) { free(context_res); context_res = NULL; - int i = 0; + i = 0; //env variable ends by NULL element while (env && env[i]) { free(env[i]); @@ -680,8 +680,7 @@ static char **__generate_argv(const char *args) GError *gerr = NULL; int i; - ret_parse = g_shell_parse_argv(args, - &argcp, &argvp, &gerr); + 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); diff --git a/src/request.c b/src/request.c index e1ed522..1053847 100644 --- a/src/request.c +++ b/src/request.c @@ -599,7 +599,6 @@ static int __handle_request_cleardata(uid_t uid, uid_t target_uid = (uid_t)-1; char *pkgtype = NULL; char *pkgid = NULL; - char *reqkey = NULL; g_variant_get(parameters, "(u&s&s)", &target_uid, &pkgtype, &pkgid); if (target_uid == (uid_t)-1 || pkgtype == NULL || pkgid == NULL) { @@ -608,11 +607,7 @@ static int __handle_request_cleardata(uid_t uid, return -1; } - reqkey = __generate_reqkey(pkgid); - if (reqkey == NULL) - return -1; - - if (_pm_queue_push(target_uid, reqkey, PKGMGR_REQUEST_TYPE_CLEARDATA, pkgtype, + 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)); @@ -839,6 +834,7 @@ static int __handle_request_add_blacklist(uid_t uid, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + free(reqkey); return -1; } @@ -875,6 +871,7 @@ static int __handle_request_remove_blacklist(uid_t uid, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + free(reqkey); return -1; } @@ -911,6 +908,7 @@ static int __handle_request_check_blacklist(uid_t uid, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + free(reqkey); return -1; } -- 2.7.4 From 8921004d200a0792a722cf16453930e290c2a9d9 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Thu, 3 Mar 2016 21:27:21 +0900 Subject: [PATCH 16/16] Fix return value when check blacklist failed It should return two integer values. Change-Id: I722a05b024466a2795cf09464947bbc6c6a0dc61 Signed-off-by: Sangyoon Jang --- src/request.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/request.c b/src/request.c index 1053847..79ff721 100644 --- a/src/request.c +++ b/src/request.c @@ -892,14 +892,14 @@ static int __handle_request_check_blacklist(uid_t uid, 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)); + g_variant_new("(ii)", PKGMGR_R_ECOMM, -1)); return -1; } reqkey = __generate_reqkey("blacklist"); if (reqkey == NULL) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ENOMEM)); + g_variant_new("(ii)", PKGMGR_R_ENOMEM, -1)); return -1; } @@ -907,7 +907,7 @@ static int __handle_request_check_blacklist(uid_t uid, PKGMGR_REQUEST_TYPE_CHECK_BLACKLIST, "pkg", pkgid, "")) { g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", PKGMGR_R_ESYSTEM)); + g_variant_new("(ii)", PKGMGR_R_ESYSTEM, -1)); free(reqkey); return -1; } -- 2.7.4