From b478d113645819525da4ed4282c2dc55b010f868 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 26 Mar 2018 16:21:32 +0900 Subject: [PATCH 2/5] libgdbus: Add common internal apis for gdbus Change-Id: I4522aa8771370086c4984d58ae0d95ecc110a808 Signed-off-by: pr.jung --- LICENSE.Apache-2.0 | 202 +++ Makefile.am | 2 + autogen.sh | 45 + configure.ac | 120 ++ packaging/libsyscommon.manifest | 5 + packaging/libsyscommon.spec | 98 ++ src/.gitignore | 2 + src/Makefile.am | 92 ++ src/libgdbus/dbus-system.c | 2701 +++++++++++++++++++++++++++++++++++++++ src/libgdbus/dbus-system.h | 497 +++++++ src/libgdbus/libgdbus.pc.in | 17 + src/shared/log-macro.h | 51 + src/shared/log.h | 30 + 13 files changed, 3862 insertions(+) create mode 100644 LICENSE.Apache-2.0 create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 packaging/libsyscommon.manifest create mode 100644 packaging/libsyscommon.spec create mode 100644 src/.gitignore create mode 100644 src/Makefile.am create mode 100644 src/libgdbus/dbus-system.c create mode 100644 src/libgdbus/dbus-system.h create mode 100644 src/libgdbus/libgdbus.pc.in create mode 100644 src/shared/log-macro.h create mode 100644 src/shared/log.h diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.Apache-2.0 @@ -0,0 +1,202 @@ + + 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/Makefile.am b/Makefile.am new file mode 100644 index 0000000..dfa49b2 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,2 @@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..3825cb5 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +set -e + +opt="$1" + +if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then + # This part is allowed to fail + cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ + chmod +x .git/hooks/pre-commit && \ + echo "Activated pre-commit hook." || : +fi + +# README and INSTALL are required by automake, but may be deleted by +# clean up rules. to get automake to work, simply touch these here, +# they will be regenerated from their corresponding *.in files by +# ./configure anyway. +touch README INSTALL + +# make sure m4 dir exist +mkdir -p m4 + +autoreconf --force --install --verbose || exit $? + +if [ "x$opt" = "xc" ]; then + set -x + ./configure $args + make clean > /dev/null +elif [ "x$opt" = "xd" ]; then + set -x + ./configure CFLAGS='-g -O0 -ftrapv' $args + make clean > /dev/null +elif [ "x$opt" = "xg" ]; then + set -x + ./configure CFLAGS='-g -Og -ftrapv' $args + make clean > /dev/null +elif [ "x$opt" = "xl" ]; then + set -x + ./configure CC=clang CFLAGS='-g -O0 -ftrapv' $args + make clean > /dev/null +elif [ "x$opt" = "xs" ]; then + set -x + scan-build ./configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args + scan-build make +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..0d033da --- /dev/null +++ b/configure.ac @@ -0,0 +1,120 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.68]) +AC_INIT([libsystem], [4.1], [walyong.cho@samsung.com]) + +dnl AC_CONFIG_MACRO_DIRS([m4]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) + +AC_USE_SYSTEM_EXTENSIONS +AC_SYS_LARGEFILE +AC_PREFIX_DEFAULT([/usr]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +LT_PREREQ(2.2) +LT_INIT([disable-static]) + +# Checks for programs. +AC_PROG_CXX +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_RANLIB + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lrt': +AC_CHECK_LIB([rt], [main]) + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h mntent.h stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_CHECK_HEADER_STDBOOL +AC_C_INLINE +AC_TYPE_INT32_T +AC_TYPE_INT64_T +AC_TYPE_MODE_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T + +# Checks for library functions. +AC_FUNC_FORK +AC_FUNC_GETMNTENT +AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK +AC_FUNC_MKTIME +AC_FUNC_REALLOC +AC_CHECK_FUNCS([dup2 getmntent gettimeofday localtime_r memset mkdir rmdir strchr strcspn strdup strndup strrchr strspn]) + +AC_CHECK_TOOL(GPERF, gperf) +if test -z "$GPERF" ; then + AC_MSG_ERROR([*** gperf not found]) +fi + +# ------------------------------------------------------------------------------ +our_cflags=" \ + -g -O2 \ + -Werror \ + -fpie" + +our_ldflags=" \ + -Wl,--as-needed \ + -Wl,--no-undefined \ + -Wl,--gc-sections \ + -Wl,-z,relro \ + -Wl,-z,now \ + -pie" + +our_cflags=$(echo $our_cflags |sed 's/\t/ /g' | sed 's/ / /g') +our_ldflags=$(echo $our_ldflags | sed 's/\t/ /g' | sed 's/ / /g') + +AC_SUBST([OUR_CFLAGS], "$our_cflags") +AC_SUBST([OUR_LDFLAGS], "$our_ldflags") + +# ------------------------------------------------------------------------------ +PKG_CHECK_MODULES(GLIB, [glib-2.0]) +PKG_CHECK_MODULES(GIO, [gio-2.0]) +PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0]) + +# ------------------------------------------------------------------------------ +AC_SUBST([LIBGDBUS_PC_REQUIRES], "libgdbus") +AC_SUBST([LIBGDBUS_PC_CFLAGS], "") +AC_SUBST([LIBGDBUS_PC_LIBS], "-L${libdir} -lgdbus") + +AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${DBUS_REQUIRES}") +AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${DBUS_CFLAGS}") +AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${DBUS_LIBS}") + +AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${GIO_REQUIRES}") +AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${GIO_CFLAGS}") +AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${GIO_LIBS}") + +AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${GIO_UNIX_REQUIRES}") +AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${GIO_UNIX_CFLAGS}") +AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${GIO_UNIX_LIBS}") + +# ------------------------------------------------------------------------------ +AC_CONFIG_FILES([Makefile + src/Makefile]) +AC_OUTPUT +AC_MSG_RESULT([ + $PACKAGE_NAME $VERSION + + prefix: ${prefix} + rootprefix: ${with_rootprefix} + datarootdir: ${datarootdir} + lib dir: ${libdir} + rootlib dir: ${with_rootlibdir} + + OUR CFLAGS: ${OUR_CFLAGS} + CFLAGS: ${CFLAGS} + OUR LDFLAGS: ${OUR_LDFLAGS} + LDFLAGS: ${LDFLAGS} +]) diff --git a/packaging/libsyscommon.manifest b/packaging/libsyscommon.manifest new file mode 100644 index 0000000..2a0cec5 --- /dev/null +++ b/packaging/libsyscommon.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/libsyscommon.spec b/packaging/libsyscommon.spec new file mode 100644 index 0000000..6cef3e8 --- /dev/null +++ b/packaging/libsyscommon.spec @@ -0,0 +1,98 @@ +Name: libsyscommon +Summary: System Libraries +Version: 4.1 +Release: 0%{?release_flags} +License: Apache-2.0 +Group: System/Libraries +Source: %{name}-%{version}.tar.gz +%if 0%{?_with_tizen} +Source1001: %{name}.manifest +%endif + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool +BuildRequires: pkgconfig(glib-2.0) >= 2.44 +BuildRequires: pkgconfig(gio-2.0) >= 2.44 +BuildRequires: pkgconfig(gio-unix-2.0) +BuildRequires: gperf + +Requires: /bin/cp + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +System utility libraries. + +%package -n libgdbus +Summary: Dbus library +License: Apache-2.0 + +%description -n libgdbus +Internal dbus library + +%package -n libgdbus-devel +Summary: Header files for dbus library +License: Apache-2.0 +Requires: libgdbus = %{version} +Requires: pkgconfig(gio-2.0) +Requires: pkgconfig(gio-unix-2.0) +Requires: pkgconfig(dbus-1) + +%description -n libgdbus-devel +Development header files for dbus library. + +%prep +%setup -q +%if 0%{?_with_tizen} +cp %{SOURCE1001} . +%endif + +%build +%if 0%{?debug_enable} +export CFLAGS=$(echo $CFLAGS | sed -e 's/^-g / /g' | sed -e 's/ -g / /g') +export CFLAGS=$(echo $CFLAGS | sed -e 's/^-O[0-9] / /g' | sed -e 's/ $-O[0-9] / /g') +export CFLAGS=$(echo $CFLAGS | sed -e 's/-Wp,-D_FORTIFY_SOURCE=2 / /g') +export CFLAGS="-O0 -g $CFLAGS" +%endif + +./autogen.sh +%configure + +make %{?_smp_mflags} + +%install +%make_install + +rm -f %{buildroot}%{_libdir}/*.la + +# make sure debugsources.list exist, it used by rpm macro in %file +# section. +touch debugsources.list + +%check +make check + +%post +/sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -n libgdbus +%defattr(-,root,root,-) +%if 0%{?_with_tizen} +%manifest %{name}.manifest +%endif +%license LICENSE.Apache-2.0 +%{_libdir}/libgdbus.so.* + +%files -n libgdbus-devel +%defattr(-,root,root,-) +%if 0%{?_with_tizen} +%manifest %{name}.manifest +%endif +%license LICENSE.Apache-2.0 +%{_libdir}/libgdbus.so +%{_includedir}/libgdbus/dbus-system.h +%{_libdir}/pkgconfig/libgdbus.pc diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..7ca4570 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/test-* \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..bbee945 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,92 @@ +AUTOMAKE_OPTIONS = color-tests parallel-tests + +pkgconfiglibdir=$(libdir)/pkgconfig + +CLEANFILES = +EXTRA_DIST = + +lib_LTLIBRARIES = +noinst_LTLIBRARIES = +noinst_DATA = +pkgconfiglib_DATA = + +check_PROGRAMS = +check_DATA = +tests= +#noinst_PROGRAMS = $(tests) +#check_PROGRAMS += $(tests) +#TESTS = $(tests) + +DEFAULT_CFLAGS = \ + $(OUR_CFLAGS) + +DEFAULT_LDFLAGS = \ + $(OUR_LDFLAGS) + +AM_CPPFLAGS = \ + -include $(top_builddir)/config.h \ + $(DEFAULT_CFLAGS) + +AM_CFLAGS = $(DEFAULT_CFLAGS) +AM_LDFLAGS = $(DEFAULT_LDFLAGS) + +INSTALL_EXEC_HOOKS = +UNINSTALL_EXEC_HOOKS = + +# ------------------------------------------------------------------------------ +pkgconfiglib_DATA += \ + libgdbus/libgdbus.pc + +EXTRA_DIST += \ + libgdbus/libgdbus.pc.in + +CLEANFILES += \ + libgdbus/libgdbus.pc + +libgdbus_pkgincludedir=$(includedir)/libgdbus +libgdbus_pkginclude_HEADERS = + +libgdbus_pkginclude_HEADERS += \ + libgdbus/dbus-system.h + +lib_LTLIBRARIES += \ + libgdbus.la + +libgdbus_la_SOURCES = \ + libgdbus/dbus-system.c + +libgdbus_la_CFLAGS = \ + $(AM_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(GIO_CFLAGS) + +libgdbus_la_LIBADD = \ + -lrt \ + $(GIO_LIBS) \ + $(GIO_UNIX_LIBS) + +# ------------------------------------------------------------------------------ +substitutions = \ + '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \ + '|PACKAGE_NAME=$(PACKAGE_NAME)|' \ + '|PACKAGE_URL=$(PACKAGE_URL)|' \ + '|LIBGDBUS_PC_REQUIRES=$(LIBGDBUS_PC_REQUIRES)|' \ + '|LIBGDBUS_PC_CFLAGS=$(LIBGDBUS_PC_CFLAGS)|' \ + '|LIBGDBUS_PC_LIBS=$(LIBGDBUS_PC_LIBS)|' \ + '|includedir=$(includedir)|' \ + '|VERSION=$(VERSION)|' + +SED_PROCESS = \ + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ + $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \ + < $< > $@ + +%.pc: %.pc.in + $(SED_PROCESS) + +%.c: %.gperf + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_GPERF)$(GPERF) < $< > $@ + +install-exec-hook: $(INSTALL_EXEC_HOOKS) diff --git a/src/libgdbus/dbus-system.c b/src/libgdbus/dbus-system.c new file mode 100644 index 0000000..22df703 --- /dev/null +++ b/src/libgdbus/dbus-system.c @@ -0,0 +1,2701 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * 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 "shared/log.h" +#include "dbus-system.h" + +/* 10 seconds */ +#define DBUS_REPLY_TIMEOUT (10000) + +int check_systemd_active(void) +{ + int ret = FALSE; + GVariant *msg = NULL; + GVariant *var = NULL; + char *state; + + _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState"); + + msg = dbus_handle_method_sync_with_reply_var("org.freedesktop.systemd1", + "/org/freedesktop/systemd1/unit/default_2etarget", + "org.freedesktop.DBus.Properties", + "Get", + g_variant_new("(ss)", "org.freedesktop.systemd1.Unit", "ActiveState")); + if (!msg) + return -EBADMSG; + + if (!dh_get_param_from_var(msg, "(v)", &var)) { + _E("reply is not variant type"); + ret = -EBADMSG; + goto out; + } + if (!dh_get_param_from_var(var, "(s)", &state)) { + _E("variant doesn't have string (%s)", g_variant_get_type_string(var)); + ret = -EBADMSG; + goto out; + } + + if (strncmp(state, "active", 6) == 0) + ret = TRUE; + + g_free(state); +out: + if (var) + g_variant_unref(var); + if (msg) + g_variant_unref(msg); + + return ret; +} + +static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM; +pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; + +void dbus_handle_set_default_bus_type(GBusType bus_type) +{ + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) + return ; + + pthread_mutex_lock(&g_mutex); + g_default_bus_type = bus_type; + pthread_mutex_unlock(&g_mutex); +} + +GBusType dbus_handle_get_default_bus_type(void) +{ + GBusType type; + + pthread_mutex_lock(&g_mutex); + type = g_default_bus_type; + pthread_mutex_unlock(&g_mutex); + + return type; +} + +typedef struct { + const char *bus_name; + guint id; +} dbus_name; + +/* basic information */ +typedef struct { + GDBusConnection *conn; + GBusType bus_type; + gboolean priv; + GList *list_names; /* dbus_name */ + GList *list_object; /* dbus_object_handle_s */ + pthread_mutex_t mutex; +} dbus_handle_s; + +/* path + interfaces */ +typedef struct { + dbus_handle_s *dh; /* dbus handle */ + const char *path; /* object path */ + GList *list_ifaces; /* dbus_interface_s */ +} dbus_object_handle_s; + +typedef struct { + dbus_object_handle_s *oh; /* object handle */ + const char *name; /* interface name */ + GList *list_methods; /* const dbus_method_s */ + guint reg_id; + int modified; +} dbus_interface_s; + +#define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh + +/* global shared bus : system, session */ +static dbus_handle_s g_dh[2]; + +static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type); + +dbus_handle_s * _dbus_handle_get_default_connection(void) +{ + return _dbus_handle_get_connection(dbus_handle_get_default_bus_type()); +} + +#define dbus_handle_lock(handle) do {\ + assert(handle);\ + pthread_mutex_lock(&((handle)->mutex));\ +} while (0); + +#define dbus_handle_unlock(handle) do {\ + assert(handle);\ + pthread_mutex_unlock(&(handle)->mutex);\ +} while (0); + +#define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle; +#define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\ + if (!dh) {\ + _E("dbus handle is null\n");\ + return 0;\ + } + +dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path); +dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name); +dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name); +static GVariant* _append_variant(const char *signature, const char *param[]); + +dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u) +{ + dbus_interface_s *iface = NULL; + + if (!iface_u || !iface_u->methods) { + _E("param is null"); + return NULL; + } + + iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s)); + if (!iface) { + _E("failed to calloc"); + return NULL; + } + + iface->name = iface_u->name; + iface->modified = TRUE; + + for (int i = 0 ; i < iface_u->nr_methods; ++i) { + //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func); + iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i)); + } + + return iface; +} + +static GDBusConnection * _get_bus(GBusType bus_type) +{ + GDBusConnection *conn = NULL; + GError *err = NULL; + + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { + _E("Wrong bus_type %d", bus_type); + return NULL; + } + + conn = g_bus_get_sync(bus_type, NULL, &err); + if (!conn || err) { + _E("failed to get bus:type:%d, %s\n", bus_type, err->message); + g_error_free(err); + return NULL; + } + + return conn; +} + +static GDBusConnection * _get_bus_private(GBusType bus_type) +{ + GError *err = NULL; + GDBusConnection *conn = NULL; + const char * address; + + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { + _E("Wrong bus_type %d", bus_type); + return NULL; + } + + address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err); + if (!address || err) { + _E("failed to get bus address\n"); + g_error_free(err); + return NULL; + } + + conn = g_dbus_connection_new_for_address_sync(address, + (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, /* GDBusAuthObserver */ + NULL, + &err); + if (!conn || err) { + _E("failed to get private bus\n"); + g_error_free(err); + return NULL; + } + + return conn; +} + +/* ref cout is 1 */ +static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type) +{ + int ibus = bus_type - 1; + dbus_handle_s *dh = NULL; + + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { + _E("Unknown bus type %d", bus_type); + return NULL; + } + dh = &g_dh[ibus]; + + dbus_handle_lock(dh); + + if (!dh->conn) { + dh->conn = _get_bus(bus_type); + dh->priv = FALSE; + dh->bus_type = bus_type; + if (!dh->conn) + dh = NULL; + } + + dbus_handle_unlock(dh); + + return dh; +} + +/* ref cout is 1 */ +static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type) +{ + dbus_handle_s * dh; + + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { + _E("Unknown bus type %d", bus_type); + return NULL; + } + + dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s)); + if (!dh) { + _E("failed to allocate memory for dbus handle"); + return NULL; + } + + dbus_handle_lock(dh); + + if (!dh->conn) { + dh->conn = _get_bus_private(bus_type); + dh->bus_type = bus_type; + if (!dh->conn) + goto err; + } + + dbus_handle_unlock(dh); + + return dh; +err: + if (dh) { + dbus_handle_unlock(dh); + free(dh); + } + return NULL; +} + +dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv) +{ + dbus_handle_s *dh = NULL; + + if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { + _E("Wrong bus_type %d\n", bus_type); + return dh; + } + + /* private */ + if (priv) + dh = _dbus_handle_get_connection_private(bus_type); + /* shared */ + else + dh = _dbus_handle_get_connection(bus_type); + + return dh; +} + +static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id) +{ + dbus_name *dn = NULL; + int locked = 0; + + if (!handle || !name || !id) + return ; + + dn = (dbus_name*)calloc(1, sizeof(dbus_name)); + if (!dn) { + _E("failed to calloc"); + assert(0); + } + dn->bus_name = name; + dn->id = id; + + // todo : delete lock ? + locked = pthread_mutex_trylock(&handle->mutex); + if (locked != 0 && locked != EBUSY) { + _E("failed to lock %d\n", locked); + assert(0); + } + + handle->list_names = g_list_prepend(handle->list_names, dn); + + // todo : delete lock ? + if (locked != EBUSY) + dbus_handle_unlock(handle); +} + +static gint _compare_dbus_name(gconstpointer a, gconstpointer b) +{ + const char *bus_name = ((dbus_name *)a)->bus_name; + if (!bus_name || !b) + return -1; + return strcmp(bus_name, (const char *)b); +} + +dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name) +{ + if (!list_name || !bus_name) + return NULL; + + GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name); + if (!item) + return NULL; + + return (dbus_name *)item->data; +} + +#define dh_to_ds(x) ((dbus_handle_s*)x) + +/* remove dbus_name from dbus handle */ +static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name) +{ + dcl_dbus_handle(); + dbus_name *dn = NULL; + + if (!bus_name) { + _E("wrong bus_name %s", bus_name); + return ; + } + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return ; + } + } + + dbus_handle_lock(dh); + dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name); + if (!dn) { + _E("failed to find dbus name %s", bus_name); + goto out; + } + dh->list_names = g_list_remove(dh->list_names, dn); + free(dn); +out: + dbus_handle_unlock(dh); +} + +//extern void booting_done(void); + +/* default handler */ +static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + dbus_handle_s *dh = (dbus_handle_s *)user_data; + + _D("name %s", name); + + if (!dh) { + _E("%s:%d:dbus handle is null\n", __func__, __LINE__); + return ; + } + + // todo: add bus name? + //dh->bus_name = name; +} + +/* default handler */ +static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + _E("%s:%d:%s\n", __func__, __LINE__, name); + dbus_handle_s *dh = (dbus_handle_s *)user_data; + if (!dh) { + _E("%s:%d:dbus handle is null\n", __func__, __LINE__); + return ; + } + _dbus_handle_remove_bus_name(dh, name); +} + +int dbus_handle_request_bus_name(dbus_handle_h handle, + const char *bus_name, + GBusNameAcquiredCallback acquired_handler, + GBusNameLostCallback lost_handler) +{ + dcl_dbus_handle(); + int id = -1; + GList *item = NULL; + + if (!bus_name) { + _E("bus_name is NULL"); + return -1; + } + + /* get shared connection */ + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + + dbus_handle_lock(dh); + if (!dh->conn) { + _E("failed to register name: connection is null\n"); + goto out; + } + + /* todo : search name on connection */ + item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name); + if (item) { + id = ((dbus_name*)(item->data))->id; + _E("name already exist:%u", id); + goto out; + } + + id = g_bus_own_name_on_connection(dh->conn, + bus_name, + G_BUS_NAME_OWNER_FLAGS_NONE, + acquired_handler ? acquired_handler : _name_acquired, + lost_handler ? lost_handler : _name_lost, + dh, + NULL); + if (!id) { + _E("failed to own name:%s\n", bus_name); + goto out; + } + + _dbus_handle_add_bus_name(dh, bus_name, id); + +out: + dbus_handle_unlock(dh); + return id; +} + +/* !! _name_lost handler callback is disabled by g_bus_unown_name : ubuntu */ +int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name) +{ + dcl_dbus_handle(); + dbus_name *dn = NULL; + + if (!bus_name) { + _E("Wrong bus name"); + return -1; + } + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + + dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name); + if (!dn) { + _E("failed to find bus_name %s on dbus handle", bus_name); + return -1; + } + + _E("unown name %d", dn->id); + /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */ + g_bus_unown_name(dn->id); + + dbus_handle_lock(dh); + dh->list_names = g_list_remove(dh->list_names, dn); + free(dn); + dbus_handle_unlock(dh); + + return 0; +} + +int dbus_handle_free_connection(dbus_handle_h handle) +{ + dcl_dbus_handle(); + dbus_handle_s *pdh = NULL; + GError *err = NULL; + GList *item = NULL; + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + + if (!dh->conn) { + _E("connection is NULL"); + return 0; + } + + pdh = dh; + + /* disable dbus handler */ + dbus_handle_lock(dh); + if (!pdh->conn) { + _E("conn is null"); + free(pdh); + return 0; + } + + /* flush everything */ + if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) { + _E("failed to flush %s\n", err->message); + g_error_free(err); + err = NULL; + } + + _D("list_names %u", g_list_length(pdh->list_names)); + + /* unown every well-knwon name */ + if (pdh->list_names) { + dbus_name *dn = NULL; + for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) { + dn = (dbus_name *)item->data; + if (!dn) + continue; + + /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */ + _D("unown name id : %u", dn->id); + g_bus_unown_name(dn->id); + free(dn); + } + g_list_free(pdh->list_names); + pdh->list_names = NULL; + } + + _D("list_object %u", g_list_length(pdh->list_object)); + + /* unregister every object */ + if (pdh->list_object) { + dbus_object_handle_s * oh = NULL; + //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data) {}, NULL); + for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) { + oh = (dbus_object_handle_s *)item->data; + if (!oh || !oh->list_ifaces) + continue; + + _D("delete object path %s", oh->path); + + /* unregister every interface, method handles */ + for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) { + dbus_interface_s *ih = (dbus_interface_s *)iface->data; + if (!ih) + continue; + + _D("delete object iface %s", ih->name); + + if (ih->reg_id) + g_dbus_connection_unregister_object(pdh->conn, ih->reg_id); + } + } + } + + /* close connection */ + if (pdh->priv) { + _E("close private connection\n"); + + if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) { + _E("Error closing connection %s\n", err->message); + g_error_free(err); + err = NULL; + } + } + + /* _free_func_object callback free the data */ + //assert(g_list_length(pdh->list_names) == 0); + //assert(g_list_length(pdh->list_object) == 0); + + g_object_unref(pdh->conn); + + dbus_handle_unlock(dh); + + if (dh->priv) + free(dh); + + return 0; + + // todo: signal ? +} + +#define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0) +#define buf_block_size 8192 + +#define buf_check_space_realloc(buf, nwrite, buf_len) do {\ + if ((nwrite >= buf_len - 1024)) {\ + if (buf_len >= buf_block_size * 10) {\ + _E("buf is too big to allocate. %d", buf_len);\ + } else {\ + _E("buf_check_space_realloc");\ + char *tmp = NULL;\ + buf_len += buf_block_size;\ + tmp = (char *)realloc(buf, buf_len);\ + if (!tmp) {\ + _E("failed to realloc");\ + } else\ + buf = tmp;\ + } \ + } \ +} while (0); + +/* cal index of end of brace */ +static int _check_brace(const char * expr) +{ + int len = 0; + char qu[128]; + int qucnt = 0; + + if (!expr) + return -1; + + len = strlen(expr); + + if (expr[0] != '(' && expr[0] != '{') + return -1; + + for (int i = 0 ; i < len; ++i) { + + if (expr[i] == '(' || expr[i] == '{') { + qu[qucnt++] = expr[i]; + if (qucnt >= sizeof(qu)) { + _E("queue is too large. %s", expr); + return -1; + } + continue; + } + + if (expr[i] == ')' || expr[i] == '}') { + char ch; + + if (qucnt > 0) + ch = qu[qucnt-1]; + else + return -1; + + if (expr[i] == ')') { + if (ch == '(') { + --qucnt; + } else + return -1; + } else if (expr[i] == '}') { + if (ch == '{') { + --qucnt; + } else + return -1; + } else + return -1; + + if (qucnt == 0) { + return i + 1; + } + } + } + + return -1; +} + +/* +in : interface_s +out : xml format +*/ +static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces) +{ + int nwrite = 0; + int len_args; + char *buf = NULL; + const dbus_method_s *pmethod; + int buf_len = buf_block_size; + + if (!interfaces) { + _E("interfaces is null"); + return -1; + } + + // todo : check dbus naming rule for interface name. ? + if (!interfaces->name) { + _E("wrong interface name"); + return -1; + } + if (!interfaces->list_methods) { + _E("no methods"); + return -1; + } + + buf = (char *)malloc(buf_len); + if (!buf) { + _E("buf is null. not enough memory\n"); + return -1; + } + + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), """\n""\t""""\n", interfaces->name); + + /* members */ + for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) { + pmethod = (const dbus_method_s *)item->data; + if (!pmethod) + continue; + + /* check free space of buf */ + buf_check_space_realloc(buf, nwrite, buf_len); + + if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) { + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n", pmethod->member); + continue; + } + + /* */ + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n", pmethod->member); + + /* in args */ + len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0; + for (int m = 0; m < len_args; ++m) { + // todo + // array a(), as, ay ? + if (pmethod->signature_in[m] == 'a') { + int ei; //end index + ei = _check_brace(pmethod->signature_in + m + 1); + if (ei > 0) { + char tmp[128] = {0,}; + strncpy(tmp, pmethod->signature_in + m, ei + 1); + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", tmp, m); + m += ei; + continue; + } else { + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m); + m += 1; + continue; + } + } + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_in[m], m); + } + + /* out args */ + len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0; + for (int m = 0; m < len_args; ++m) { + // array + // todo: container type + if (pmethod->signature_out[m] == 'a') { + int ei; //end index + ei = _check_brace(pmethod->signature_out + m + 1); + if (ei > 0) { + char tmp[128] = {0,}; + strncpy(tmp, pmethod->signature_out + m, ei + 1); + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", tmp, m); + m += ei; + continue; + } else { + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m); + m += 1; + continue; + } + } + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_out[m], m); + } + + /* */ + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n"); + } + + nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""""\n"""""); + + *xml = buf; + + /* todo: delete log */ +#if 0 + if (nwrite <= 512) + _E("%s", buf); + else + _E("%s", buf + nwrite - 512); +#endif + return 0; +} + +static gint _compare_dbus_object(gconstpointer a, gconstpointer b) +{ + dbus_object_handle_s * pa = (dbus_object_handle_s *)a; + if (!pa->path || !((const char*)b)) + return -1; + return strcmp(pa->path, (const char*)b); +} + +static gint _compare_dbus_interface(gconstpointer a, gconstpointer b) +{ + dbus_interface_s * pa = (dbus_interface_s *)a; + if (!pa->name || !((const char*)b)) + return -1; + return strcmp(pa->name, (const char*)b); +} + +static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b) +{ + dbus_interface_s * pa = (dbus_interface_s *)a; + if (!pa->reg_id || !((guint*)b)) + return -1; + return !(pa->reg_id == *((guint*)b)); +} + +static gint _compare_dbus_method(gconstpointer a, gconstpointer b) +{ + dbus_method_s *pa = (dbus_method_s*)a; + if (!pa->member || !((const char*)b)) + return -1; + return strcmp(pa->member, (const char*)b); +} + +dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path) +{ + if (!list_obj || !obj_path) + return NULL; + + GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object); + if (!item) + return NULL; + + return (dbus_object_handle_s *)item->data; +} + +dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name) +{ + if (!list_iface || !iface_name) + return NULL; + + GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface); + if (!item) + return NULL; + + return (dbus_interface_s *)item->data; +} + +dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id) +{ + if (!list_iface || !id) + return NULL; + + GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id); + if (!item) + return NULL; + + return (dbus_interface_s *)item->data; +} + +dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name) +{ + if (!list_methods || !method_name) + return NULL; + + GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method); + if (!item) + return NULL; + + return (dbus_method_s *)item->data; +} + +static void _free_func_object(gpointer data) +{ + dbus_interface_s *ih = (dbus_interface_s *)data; + dbus_object_handle_s *oh = NULL; + + if (!ih) { + _E("interface handle is null"); + assert(0); // something wrong + return ; + } + + _E("unregister interface %s", ih->name); + + /* just free list, not data(static dbus_method_s) */ + g_list_free(ih->list_methods); + + oh = ih->oh; + if (!oh) { + _E("object handle is null"); + assert(0); // something wrong + return ; + } + + /* remove ih from list_ifaces */ + oh->list_ifaces = g_list_remove(oh->list_ifaces, ih); + + /* interface_s is copy of interface_u */ + free(ih); + + /* remove oh from list_object */ + if (!oh->list_ifaces) { + oh->dh->list_object = g_list_remove(oh->dh->list_object, oh); + free(oh); + } +} + +static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface) +{ + dbus_object_handle_s *oh = NULL; + + if (!dh || !obj_path || !iface) { + _E("failed to attache object. wrong parameter"); + return -1; + } + + /* find object handle */ + if (dh->list_object) + oh = _dbus_handle_lookup_object(dh->list_object, obj_path); + + if (!oh) { + oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s)); + if (!oh) { + _E("failed to calloc"); + return -1; + } + oh->dh = dh; + oh->path = obj_path; + + /* attach object */ + dh->list_object = g_list_prepend(dh->list_object, oh); + } + + iface->oh = oh; + /* attach interface */ + oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface); + + return 0; +} + +/* +_method_call_handler + +libgio verify path and interface of incoming message. +--> just check method name. + +# parameters - member of invocation struct +every parameters of this function are member of GDBusMethodInvocation *invocation. +There are no reason to using g_dbus_method_invocation_get_* apis to get inforamtion from message. +just use params - sender, path, iface, name and param. + + +# user defined handler # + +1. synchronous handling + 1) with return value + handler() { + return g_variant_new("(i)", ret); + } + + 2) without return value + handler() { + return dbus_handle_new_g_variant_tuple(); // g_variant_new_tuple(NULL, 0) + } + +2. asynchronous handling + handler MUST call 'g_dbus_method_invocation_return_value' itself. otherwise, LEAK !! + + handler() { + return NULL; + } + + # if handler return NULL, assume asynchronous handling. do nothing. + + thread() { + do something; + + 1) with return value + g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret)); + + 2) without return value + g_dbus_method_invocation_return_value(invocation, NULL); + } + + +*/ +static void _method_call_handler(GDBusConnection *conn, + const gchar *sender, + const gchar *path, + const gchar *iface, + const gchar *name, + GVariant *param, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + dbus_interface_s *iface_s = (dbus_interface_s *)user_data; + const dbus_method_s *methods; + GVariant *result = NULL; + + /* todo: ghash ? */ + methods = _dbus_handle_lookup_method(iface_s->list_methods, name); + if (methods) { + result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh)); + + /* async, maybe they will reply...maybe.. */ + if (!result) + return; + } else { + _E("no methods"); + } + + g_dbus_method_invocation_return_value(invocation, result); +} + +static GDBusInterfaceVTable path_vtable = {_method_call_handler}; + + +/* +before register object, attach object into dbus handle +_dbus_handle_attach_object() +*/ +static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface) +{ + dcl_dbus_handle(); + int ret = 0; + char *buf = NULL; + GError *err = NULL; + GDBusNodeInfo * nodeinfo = NULL; + GDBusInterfaceInfo *ifaceinfo = NULL; + + if (!obj_path || !iface) { + _E("wrong parameter\n"); + return -1; + } + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + if (!dh->conn) { + _E("connection is null\n"); + return -1; + } + + ret = _get_xml_from_interfaces(&buf, iface); + if (ret < 0) { + _E("failed to make xml format"); + goto err; + } + + /* todo: delete this */ +#if 0 + if (strlen(buf) <= 512) { + _E("%s", buf); + } else { + _E("%s", buf + strlen(buf) - 512); + } +#endif + + nodeinfo = g_dbus_node_info_new_for_xml(buf, &err); + if (!nodeinfo || err) { + _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf); + ret = -1; + goto err; + } + + ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name); + if (!ifaceinfo) { + _E("failed to g_dbus_node_info_lookup_interface"); + ret = -1; + goto err; + } + + /* + path own single interface + if interface is already registered, then failed. + g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered + */ + ret = g_dbus_connection_register_object(dh->conn, + obj_path, + ifaceinfo/*ref 2*/, + &path_vtable, + (void*)iface, + _free_func_object, + &err); + if (err) { + _E("failed to register object:err:%s:\n", err->message); + ret = -1; + goto err; + } + + iface->reg_id = ret; + iface->modified = FALSE; + +err: + /* todo: detach object */ + //_dbus_handle_detach_object(dh, obj_path, iface); + /* attach interface before register object */ + /*ret = _dbus_handle_detach_object(dh, obj_path, iface); + if (ret < 0) { + _E("failed to attach object"); + goto err; + }*/ + + if (nodeinfo) + g_dbus_node_info_unref(nodeinfo); + if (buf) + free(buf); + if (err) + g_error_free(err); + + return ret; +} + +/* +register same interface at once + +if interface is constructed by multiple methods, +also it is not possible to make methods struct at once, + +use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all(). + +return reg_id +*/ +int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u) +{ + dcl_dbus_handle(); + int ret = 0; + dbus_interface_s *iface = NULL; + + if (!obj_path || !iface_u) { + _E("wrong parameter\n"); + return -1; + } + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + if (!dh->conn) { + _E("connection is null\n"); + return -1; + } + + /* check registered interface */ + if (dh->list_object) { + dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path); + if (oh) { + dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name); + if (ih) { + _E("path %s, interface %s already registered", obj_path, iface_u->name); + return -1; + } + } + } + + iface = _iface_u_to_s(iface_u); + if (!iface) { + _E("failed to _iface_u_to_s"); + return -1; + } + + /* attach interface before register object */ + ret = _dbus_handle_attach_object(dh, obj_path, iface); + if (ret < 0) { + _E("failed to attach object"); + goto err; + } + + ret = _dbus_handle_register_dbus_object(dh, obj_path, iface); + if (ret <= 0) { + _E("failed to register dbus object%d", ret); + goto err; + } +err: + return ret; +} + +int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path) +{ + dcl_dbus_handle(); + dbus_object_handle_s *oh = NULL; + int ret = 0; + + if (!obj_path) { + return -1; + } + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + if (!dh->list_object) { + _E("list_object is empty"); + return 0; + } + + oh = _dbus_handle_lookup_object(dh->list_object, obj_path); + if (!oh) { + _E("no object with name %s", obj_path); + return -1; + } + + /* unregister every interface of object*/ + for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) { + dbus_interface_s *ih = item->data; + if (!ih) { + _E("this is error"); + assert(0); + } + + /* remove ih from list_ifaces */ + if (!ih->reg_id) { + item = g_list_previous(item); + + /* remove and free link */ + oh->list_ifaces = g_list_remove(oh->list_ifaces, ih); + + /* free list_methods */ + g_list_free(ih->list_methods); + + /* free data */ + free(ih); + continue; + } + + /* unregister object by id */ + ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id); + if (!ret) + _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id); + } + + return 0; +} + +/* +add object temporarily. +dbus_handle_register_dbus_object_all register every objects on connection. + +return registered method count +*/ +int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u) +{ + dcl_dbus_handle(); + dbus_object_handle_s *oh = NULL; + dbus_interface_s *ih = NULL; + int cnt; + + if (!obj_path || !iface_u) { + _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u); + return -1; + } + if (iface_u && (!iface_u->name || !iface_u->methods)) { + _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u); + return -1; + } + + cnt = iface_u->nr_methods; + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + + if (!dh->conn) { + _E("failed to register method. connection is null\n"); + return -1; + } + + /* if there are no object list, just add */ + if (!dh->list_object) { + if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { + _E("failed to attach object"); + return -1; + } + goto out; + } + + oh = _dbus_handle_lookup_object(dh->list_object, obj_path); + /* if there are no matched object, just add */ + if (!oh) { + if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { + _E("failed to attach object"); + return -1; + } + goto out; + } + + /* this is an error, interface must have one or more item ? */ + if (!oh->list_ifaces) { + _E("error. list_ifaces is null\n"); + assert(0); + goto out; + } + + ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name); + /* if there are no matched interface, just add */ + if (!ih) { + if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { + _E("failed to attach object"); + return -1; + } + goto out; + } + + /* todo: + 1. unregister interface + 2. update interface and methods + 3. register interface + */ + if (ih->reg_id) { + _E("interface already registered, ignore new interface"); + return -1; + } + + /* attach new methods */ + cnt = 0; + for (int i = 0; i < iface_u->nr_methods; ++i) { + GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method); + if (!item) { + //_D("attached %s", iface_u->methods[i].member); + ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i)); + ++cnt; + } + } + + if (cnt) + ih->modified = TRUE; + +out: + /*todo: delete debugging log */ + //if (dh && dh->list_object) + // _D("obj list len %d", g_list_length(dh->list_object)); + //if (oh && oh->list_ifaces) + // _D("iface list len %d", g_list_length(oh->list_ifaces)); + //if (ih && ih->list_methods) + // _D("method list len %d", g_list_length(ih->list_methods)); + + return cnt; +} + +int dbus_handle_register_dbus_object_all(dbus_handle_h handle) +{ + dcl_dbus_handle(); + dbus_object_handle_s *oh = NULL; + dbus_interface_s *ih = NULL; + int ret = 0; + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + if (!dh->conn) { + _E("connection is null\n"); + return -1; + } + + if (!dh->list_object) { + _E("obj list is empty"); + return -1; + } + + /*if (dh && dh->list_object) + _D("obj list len %d", g_list_length(dh->list_object));*/ + + for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) { + oh = (dbus_object_handle_s *)item->data; + + if (!oh) { + _E("something wrong"); + assert(0); + } + if (!oh->list_ifaces) { + _E("path %s: list_ifaces are null", oh->path); + goto err; + } + + //_D("iface list len %d", g_list_length(oh->list_ifaces)); + + for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) { + ih = (dbus_interface_s *)li->data; + + /* if there are no modification, goto next */ + if (!ih->modified) + continue; + + /* todo: if already registered interface, unregister first */ + + /*_E("interface %s:", ih->name); + if (ih && ih->list_methods) + _D("method list len %d", g_list_length(ih->list_methods));*/ + + ret = _dbus_handle_register_dbus_object(dh, oh->path, ih); + if (ret <= 0) + _E("failed to register dbus object%d", ret); + + } + } + return 0; +err: + + // todo: delete all updates + + return -1; +} + +static void _free_func_signal(gpointer data) +{ + //_D("free signal subscribe"); +} + +guint subscribe_dbus_signal(dbus_handle_h handle, const char *path, + const char *iface, const char *name, + GDBusSignalCallback cb, void *data, + destroy_notified free_func) +{ + dcl_dbus_handle(); + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return 0; + } + } + + if (!dh->conn) { + _E("connection is null. check bus status"); + return 0; + } + return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, _free_func_signal); +} + +void unsubscribe_dbus_signal(dbus_handle_h handle, guint id) +{ + dcl_dbus_handle(); + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return; + } + } + + if (!dh->conn) { + _E("connection is null. check bus status"); + return; + } + + g_dbus_connection_signal_unsubscribe(dh->conn, id); +} + +int _check_type_string_is_container(const char *signature) +{ + if (!signature) + return FALSE; + + switch (signature[0]) { + case 'a': + case 'm': + case 'r': + case '(': + case '{': + case 'v': + return TRUE; + default: + return FALSE; + } + + return TRUE; +} + +GVariant *dbus_handle_make_simple_array(const char *sig, int *param) +{ + GVariantBuilder *builder = NULL; + GVariant *var = NULL; + char format[256]; + int i = 0; + + builder = g_variant_builder_new(G_VARIANT_TYPE(sig)); + if (!builder) { + _E("failed to g_variant_builder_new"); + return NULL; + } + + while (param[i]) + g_variant_builder_add(builder, "i", param[i++]); + + snprintf(format, sizeof(format) - 1, "(%s)", sig); + var = g_variant_new(format, builder); + g_variant_builder_unref(builder); + return var; +} + +/* todo: looks like garbage... */ +static GVariant* _append_variant(const char *signature, const char *param[]) +{ + char *ch; + int i; + int pi; + int int_type; + gboolean bool_type; + unsigned long long int64_type; + GVariant *ret; + int len; + char container[255];// The maximum length of a signature is 255. + const char *sig = signature; + GVariantBuilder *builder = NULL; + + if (!signature || !param) + return 0; + + /* workaround for user fault "(i) != i" but we treat this as same signature */ + /* G_VARIANT_TYPE("si") return NULL */ + /* todo: actually user have to use correct signature */ + if (!_check_type_string_is_container(signature)) { + snprintf(container, sizeof(container) - 1, "(%s)", signature); + sig = container; + } + if (!g_variant_type_is_container(G_VARIANT_TYPE(sig))) { + _E("signature (%s) is not container type", signature); + } + + builder = g_variant_builder_new(G_VARIANT_TYPE(sig)); + len = strlen(sig); + pi = 0; + for (ch = (char *)sig, i = 0; i < len; ++i, ++ch) { + switch (*ch) { + case '(': + case ')': + continue; + case 'b': + bool_type = (atoi(param[pi++]) == 0 ? FALSE : TRUE); + g_variant_builder_add(builder, "b", bool_type); + break; + case 'i': + int_type = atoi(param[pi++]); + g_variant_builder_add(builder, "i", int_type); + break; + case 'u': + int_type = strtoul(param[pi++], NULL, 10); + g_variant_builder_add(builder, "u", int_type); + break; + case 't': + int64_type = atoll(param[pi++]); + g_variant_builder_add(builder, "t", int64_type); + break; + case 's': + g_variant_builder_add(builder, "s", param[pi++]); + break; + case 'a': + ++ch; + switch (*ch) { + case 'y': + g_variant_builder_add(builder, "^ay", param[pi++]); + ++i; + break; + default: + break; + } + break; + default: + break; + } + } + ret = g_variant_builder_end(builder); + g_variant_builder_clear(builder); + g_variant_builder_unref(builder); + + return ret; +} + +int dbus_handle_broadcast_dbus_signal(const char *path, + const char *iface, + const char *name, + const char *signature, + const char *param[]) +{ + dbus_handle_s *dh = NULL; + GError *err = NULL; + gboolean ret = 0; + GVariant *var = NULL; + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + if (signature && param) + var = _append_variant(signature, param); + ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, var, &err); + if (err) { + _E("%d %s\n", ret, err ? err->message : NULL); + g_error_free(err); + } + + return ret; +} + +int dbus_handle_broadcast_dbus_signal_var(const char *path, + const char *iface, + const char *name, + GVariant *param) +{ + dbus_handle_s *dh = NULL; + GError *err = NULL; + gboolean ret = 0; + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, param, &err); + if (err) { + _E("%d %s\n", ret, err ? err->message : NULL); + g_error_free(err); + } + + return ret; +} + +GVariant *dbus_handle_method_sync_with_reply_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *var) +{ + GError *err = NULL; + GVariant * ret = NULL; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + if (var) + g_variant_unref(var); + return NULL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + if (var) + g_variant_unref(var); + return NULL; + } + + ret = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); + if (!ret || err) { + if (err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_connection_call_sync"); + } + return NULL; + } + + return ret; +} + +GVariant *dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path, + const char *iface, const char *method, GVariant *var, int timeout) +{ + GError *err = NULL; + GVariant * ret = NULL; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + if (var) + g_variant_unref(var); + return NULL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + if (var) + g_variant_unref(var); + return NULL; + } + + ret = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout, NULL, &err); + if (!ret || err) { + if (err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_connection_call_sync"); + } + return NULL; + } + + return ret; +} + +gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size) +{ + GUnixFDList *fd_list = NULL; + int length = 0; + + fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation)); + + if (!fd_list) { + _E("failed to g_unix_fd_list_get_length: fd_list is null"); + return NULL; + } + + length = g_unix_fd_list_get_length(fd_list); + if (length == 0) { + _E("failed to g_unix_fd_list_get_length: list size is 0"); + return NULL; + } + if (size) + *size = length; + + return g_unix_fd_list_steal_fds(fd_list, NULL); +} + +GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[], + int *in_fdlist, + int in_size, + int **out_fdlist, + int *out_size) +{ + GError *err = NULL; + GVariant * var = NULL; + GVariant * ret = NULL; + dbus_handle_s *dh = NULL; + GDBusProxy *proxy = NULL; + GUnixFDList *g_infdlist = NULL; + GUnixFDList *g_outfdlist = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return NULL; + } + if (in_fdlist && in_size == 0) { + _E("wrong in_fdlist is not null but in_size is 0"); + return NULL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return NULL; + } + + if (signature && param) + var = _append_variant(signature, param); + + proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err); + if (!proxy) { + if (err) { + _E("failed to proxy_new_sync(%s)\n", err->message); + g_error_free(err); + } else { + _E("failed to proxy_new_sync\n"); + if (var) + g_variant_unref(var); + } + } + + /* append fd */ + if (in_fdlist) { + g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size); + if (!g_infdlist) { + _E("failed to g_unix_fd_list_new_from_array\n"); + goto out; + } + //g_infdlist = g_unix_fd_list_new(); + //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) { + } + + ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, var, G_DBUS_CALL_FLAGS_NONE, -1, + g_infdlist, &g_outfdlist, NULL, &err); + if (!ret || err) { + if (err) { + _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:"); + if (var) + g_variant_unref(var); + if (g_infdlist) + g_object_unref(g_infdlist); + } + goto out; + } + + /* fds to out array */ + if (g_outfdlist) { + *out_size = g_unix_fd_list_get_length(g_outfdlist); + if (*out_size == 0) + goto out; + + *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL); + } + +out: + if (g_outfdlist) + g_object_unref(g_outfdlist); + if (proxy) + g_object_unref(proxy); + + return ret; +} + +GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + int *in_fdlist, + int in_size, + int **out_fdlist, + int *out_size) +{ + GError *err = NULL; + GVariant * ret = NULL; + dbus_handle_s *dh = NULL; + GDBusProxy *proxy = NULL; + GUnixFDList *g_infdlist = NULL; + GUnixFDList *g_outfdlist = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return NULL; + } + if (in_fdlist && in_size == 0) { + _E("wrong in_fdlist is not null but in_size is 0"); + return NULL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return NULL; + } + + proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err); + if (!proxy) { + if (err) { + _E("failed to proxy_new_sync(%s)\n", err->message); + g_error_free(err); + } else { + _E("failed to proxy_new_sync\n"); + if (param) + g_variant_unref(param); + } + goto out; + } + + /* append fd */ + if (in_fdlist) { + g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size); + if (!g_infdlist) { + _E("failed to g_unix_fd_list_new_from_array\n"); + goto out; + } + //g_infdlist = g_unix_fd_list_new(); + //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) { + } + + /* send message */ + ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1, + g_infdlist, &g_outfdlist, NULL, &err); + if (!ret || err) { + if (err) { + _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:"); + if (param) + g_variant_unref(param); + if (g_infdlist) + g_object_unref(g_infdlist); + } + goto out; + } + + /* copy fds to out array */ + if (g_outfdlist) { + *out_size = g_unix_fd_list_get_length(g_outfdlist); + if (*out_size == 0) + goto out; + *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL); + } +out: + if (g_outfdlist) + g_object_unref(g_outfdlist); + if (proxy) + g_object_unref(proxy); + return ret; +} + +int dbus_handle_method_sync(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[]) +{ + int result; + gboolean result_bool; + GVariant *reply = NULL; + GVariant * var = NULL; + GError *err = NULL; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -ECOMM; + } + + if (signature && param) + var = _append_variant(signature, param); + + reply = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); + if (!reply || err) { + if (err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_connection_call_sync"); + g_variant_unref(var); + } + return -ECOMM; + } + + if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(i)", &result); + } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(b)", &result_bool); + result = (int)result_bool; + } else { + result = -ENOMSG; + } + + g_variant_unref(reply); + + return result; +} + +int dbus_handle_method_sync_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param) +{ + int result; + gboolean result_bool; + GVariant *reply = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + reply = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param); + if (!reply) + return -ECOMM; + + if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(i)", &result); + } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(b)", &result_bool); + result = (int)result_bool; + } else { + result = -ENOMSG; + } + + g_variant_unref(reply); + + return result; +} + +int dbus_handle_method_sync_timeout(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[], + int timeout) +{ + dbus_handle_s *dh = NULL; + GError *err = NULL; + GVariant * var = NULL; + GVariant * reply = NULL; + int result = 0; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -EPERM; + } + + if (signature && param) + var = _append_variant(signature, param); + + reply = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout, NULL, &err); + if (!reply || err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + return -1; + } + + if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) + g_variant_get(reply, "(i)", &result); + else + result = -ENOMSG; + + g_variant_unref(reply); + + return result; +} + +int dbus_handle_method_sync_pairs(const char *dest, + const char *path, + const char *iface, + const char *method, + int num, + va_list args) +{ + GError *err = NULL; + GVariant * reply = NULL; + char *key, *value; + int ret = 0; + GVariant *var; + GVariantBuilder *builder; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); + + for (int i = 0 ; i < num ; i = i + 2) { + key = va_arg(args, char *); + value = va_arg(args, char *); + _I("key(%s), value(%s)", key, value); + g_variant_builder_add(builder, "{ss}", key, value); + } + + var = g_variant_new("(a{ss})", builder); + g_variant_builder_unref(builder); + + reply = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); + if (!reply || err) { + _E("failed to g_dbus_connection_call_sync"); + return -1; + } + + if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) + g_variant_get(reply, "(i)", &ret); + else + ret = -ENOMSG; + + g_variant_unref(reply); + + return ret; +} + +int dbus_handle_method_async_pairs(const char *dest, + const char *path, + const char *iface, + const char *method, + int num, + va_list args) +{ + char *key, *value; + GVariant *var; + GVariantBuilder *builder; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + // dict + builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); + + for (int i = 0 ; i < num ; i = i + 2) { + key = va_arg(args, char *); + value = va_arg(args, char *); + _I("key(%s), value(%s)", key, value); + g_variant_builder_add(builder, "{ss}", key, value); + } + + var = g_variant_new("(a{ss})", builder); + g_variant_builder_unref(builder); + + g_dbus_connection_call(dh->conn, dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + NULL, + NULL); + + return 0; +} + +int dbus_handle_method_async(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[]) +{ + GVariant * var = NULL; + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + if (signature && param) + var = _append_variant(signature, param); + + g_dbus_connection_call(dh->conn, dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + NULL, + NULL); + + return 0; +} + +int dbus_handle_method_async_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param) +{ + dbus_handle_s *dh = NULL; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + + g_dbus_connection_call(dh->conn, dest, path, iface, method, + param, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + NULL, + NULL); + + return 0; +} + +/* callback should free gvariant */ +static void _cb_pending(GDBusConnection *conn, + GAsyncResult *res, + gpointer user_data) +{ + GVariant *reply = NULL; + GError *err = NULL; + pending_call_data *data = (pending_call_data *)user_data; + + reply = g_dbus_connection_call_finish(conn, res, &err); + if (!reply || err) { + if (err) { + _E("no message : [%s]", err->message); + g_error_free(err); + } else { + _E("no message"); + } + + if (data && data->func) + data->func(NULL, data->data, err); + goto out; + } + + if (data && data->func) + data->func(reply, data->data, err); +out: + if (data) + free(data); +} + +int dbus_handle_method_async_with_reply(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[], + dbus_pending_cb cb, + int timeout_msec, + void *data) +{ + dbus_handle_s *dh = NULL; + pending_call_data *pdata = NULL; + GVariant * var = NULL; + int ret = 0; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + if (timeout_msec < -1) { + _E("wrong timeout %d", timeout_msec); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -EPERM; + } + + if (signature && param) + var = _append_variant(signature, param); + + if (cb) { + pdata = (pending_call_data*)malloc(sizeof(pending_call_data)); + if (!pdata) { + ret = -ENOMEM; + goto err; + } + + pdata->func = cb; + pdata->data = data; + } + g_dbus_connection_call(dh->conn, dest, path, iface, method, + var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL, + (GAsyncReadyCallback)_cb_pending, + pdata); + + return ret; +err: + if (var) + g_variant_unref(var); + return ret; +} + +int dbus_handle_method_async_with_reply_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + dbus_pending_cb cb, + int timeout_msec, + void *data) +{ + dbus_handle_s *dh = NULL; + pending_call_data *pdata = NULL; + int ret = 0; + + if (!dest || !path || !iface || !method) { + _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); + return -1; + } + + if (timeout_msec < -1) { + _E("wrong timeout %d", timeout_msec); + return -1; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -EPERM; + } + + if (cb) { + pdata = (pending_call_data*)malloc(sizeof(pending_call_data)); + if (!pdata) { + ret = -ENOMEM; + goto err; + } + + pdata->func = cb; + pdata->data = data; + } + g_dbus_connection_call(dh->conn, dest, path, iface, method, + param, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL, + (GAsyncReadyCallback)_cb_pending, + pdata); + + return ret; +err: + if (param) + g_variant_unref(param); + return ret; +} + +int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender) +{ + GError *err = NULL; + GVariant *vret = NULL; + pid_t pid = 0; + + if (!conn) { + _E("connection is null"); + return -1; + } + if (!sender) { + _E("sender is null"); + return -1; + } + + vret = g_dbus_connection_call_sync(conn, + "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID", + g_variant_new("(s)", sender), + NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, + NULL, + &err); + if (!vret || err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + return -1; + } + + g_variant_get(vret, "(u)", &pid); + g_variant_unref(vret); + + return pid; +} + +int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender) +{ + dcl_dbus_handle(); + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + if (!dh->conn) { + _E("wrong dbus handle. connection is null"); + assert(0); + return -1; + } + + return dbus_connection_get_sender_pid(dh->conn, sender); +} + +int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds) +{ + dcl_dbus_handle(); + GVariant *vret = NULL; + GError *err = NULL; + GVariantIter *iter = NULL; + char * item; + GVariant *sub; + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -1; + } + } + vret = g_dbus_connection_call_sync(dh->conn, + DBUS_BUS_NAME, + DBUS_OBJECT_PATH, + DBUS_INTERFACE_NAME, + "GetConnectionCredentials", + g_variant_new("(s)", name), + NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, + NULL, + &err); + if (!vret || err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + return -1; + } + + g_variant_get(vret, "(a{sv})", &iter); + + while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) { + if (!g_strcmp0(item, "UnixUserID")) { + g_variant_get(sub, "u", &creds->uid); + //_D("UnixUserID %u", creds->uid); + } else if (!g_strcmp0(item, "ProcessID")) { + g_variant_get(sub, "u", &creds->pid); + //_D("ProcessID %u", creds->pid); + } else if (!g_strcmp0(item, "LinuxSecurityLabel")) { + g_variant_get(sub, "^ay", &creds->sec_label); + //_D("%s", creds->sec_label); + } + } + + if (iter) + g_variant_iter_free(iter); + if (vret) + g_variant_unref(vret); + + return 0; +} + +void _destroy_notify_watch_name(gpointer data) +{ +// if (data) +// free(data); +} + +int dbus_handle_watch_name(const char *name, + GBusNameAppearedCallback name_appeared_handler, + GBusNameVanishedCallback name_vanished_handler, + void *user_data, + GDestroyNotify user_data_free_func) +{ + guint id = 0; + + if (!name) { + _E("wrong name name %s", name); + return -1; + } + if (!name_appeared_handler && !name_vanished_handler) { + _E("both function pointers are null"); + return -1; + } + + id = g_bus_watch_name(dbus_handle_get_default_bus_type(), + name, + G_BUS_NAME_WATCHER_FLAGS_NONE, + name_appeared_handler, + name_vanished_handler, + user_data, + user_data_free_func ? user_data_free_func : _destroy_notify_watch_name); + if (!id) { + _E("failed to g_bus_watch_name"); + return -1; + } + + return id; +} + +void dbus_handle_unwatch_name(guint id) +{ + if (id == 0) { + _E("wrong id %d", id); + return; + } + g_bus_unwatch_name(id); +} + +int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) +{ + int fd, ret; + char buf[PATH_MAX + 1]; + char *filename; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) { + errno = ESRCH; + return -1; + } + + ret = read(fd, buf, PATH_MAX); + close(fd); + if (ret < 0) + return -1; + + buf[PATH_MAX] = '\0'; + + filename = strrchr(buf, '/'); + if (filename == NULL) + filename = buf; + else + filename = filename + 1; + + if (cmdline_size < strlen(filename) + 1) { + errno = EOVERFLOW; + return -1; + } + + strncpy(cmdline, filename, cmdline_size - 1); + cmdline[cmdline_size - 1] = '\0'; + return 0; +} + +// g_strfreev(strv) +char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name) +{ + dcl_dbus_handle(); + GError *err = NULL; + GVariant *vret = NULL; + GVariantIter *iter = NULL; + gchar **strv = NULL; + gchar *str = NULL; + int i = 0; + + if (!bus_name) { + _E("wrong parameter bus_name(%s)", bus_name); + return NULL; + } + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return NULL; + } + } + + vret = g_dbus_connection_call_sync(dh->conn, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "ListQueuedOwners", + g_variant_new("(s)", bus_name), + NULL, + G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, + NULL, + &err); + if (!vret || err) { + _E("failed to g_dbus_connection_call_sync:%s", err->message); + g_error_free(err); + return NULL; + } + + g_variant_get(vret, "(as)", &iter); + strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1); + + i = 0; + while (g_variant_iter_loop(iter, "s", &str)) + strv[i++] = g_strdup(str); + strv[i] = NULL; + + g_variant_iter_free(iter); + g_variant_unref(vret); + + return strv; +} + +void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name) +{ + dcl_dbus_handle(); + char exe_name[PATH_MAX]; + int pid; + char **strv = NULL; + int i; + + if (!dh) { + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return ; + } + } + + strv = dbus_handle_get_owner_list(dh, owner_name); + if (!strv) { + _E("failed to get owner list of %s", owner_name); + return ; + } + + for (i = 0; strv[i] != NULL; ++i) { + pid = dbus_handle_get_sender_pid(dh, strv[i]); + if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0) + break; + _I("%s(%d)", exe_name, pid); + } + + g_strfreev(strv); +} + +dbus_handle_h dbus_handle_init(GBusType type, + const char* bus_name, + GBusNameAcquiredCallback acquired_handler, + GBusNameLostCallback lost_handler) +{ + dbus_handle_h handle = NULL; + int i, ret = 0; + + if (!bus_name) { + _E("Wrong bus name"); + return NULL; + } + + // todo: do we need retry ? - booting time + for (i = 0 ; i < 3; ++i) { + handle = dbus_handle_get_connection(type, FALSE); + if (handle) + break; + usleep(5000); + } + ret = dbus_handle_request_bus_name(handle, bus_name, acquired_handler, lost_handler); + if (ret <= 0) + goto out; + + dbush_handle_check_owner_name(NULL, bus_name); + + return handle; + +out: + return NULL; +} diff --git a/src/libgdbus/dbus-system.h b/src/libgdbus/dbus-system.h new file mode 100644 index 0000000..42f2f8f --- /dev/null +++ b/src/libgdbus/dbus-system.h @@ -0,0 +1,497 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * 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 __DBUS_H__ +#define __DBUS_H__ + +#include +#include +#include +#include +#include +#include + +/* + * Template + * +#define XXX_BUS_NAME "org.tizen.system.XXX" +#define XXX_OBJECT_PATH "/Org/Tizen/System/XXX" +#define XXX_INTERFACE_NAME XXX_BUS_NAME +#define XXX_PATH_YYY XXX_OBJECT_PATH"/YYY" +#define XXX_INTERFACE_YYY XXX_INTERFACE_NAME".YYY" +#define XXX_SIGNAL_ZZZ "ZZZ" +#define XXX_METHOD_ZZZ "ZZZ" + */ + +/******************************************************************************* + * + * DBus daemon + * + ******************************************************************************/ +#define DBUS_BUS_NAME "org.freedesktop.DBus" +#define DBUS_OBJECT_PATH "/org/freedesktop/DBus" +#define DBUS_INTERFACE_NAME DBUS_BUS_NAME + +/******************************************************************************* + * + * System daemon (systemd) + * + ******************************************************************************/ +#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" +#define SYSTEMD_DBUS_DEST "org.freedesktop.systemd1" +#define SYSTEMD_DBUS_IFACE_MANAGER SYSTEMD_DBUS_DEST ".Manager" +#define SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED "StartupFinished" + +/******************************************************************************* + * + * Device daemon (deviced) + * + ******************************************************************************/ +#define DEVICED_BUS_NAME "org.tizen.system.deviced" +#define DEVICED_OBJECT_PATH "/Org/Tizen/System/DeviceD" +#define DEVICED_INTERFACE_NAME DEVICED_BUS_NAME +/* Core service: get/set device status operations about device */ +#define DEVICED_PATH_CORE DEVICED_OBJECT_PATH"/Core" +#define DEVICED_INTERFACE_CORE DEVICED_INTERFACE_NAME".core" +/* Display service: start/stop display(pm), get/set brightness operations about display */ +#define DEVICED_PATH_DISPLAY DEVICED_OBJECT_PATH"/Display" +#define DEVICED_INTERFACE_DISPLAY DEVICED_INTERFACE_NAME".display" +/* Pass service: start/stop pass operations about pass */ +#define DEVICED_PATH_PASS DEVICED_OBJECT_PATH"/Pass" +#define DEVICED_INTERFACE_PASS DEVICED_INTERFACE_NAME".pass" +/* Power service: set resetkey disable operations about power */ +#define DEVICED_PATH_POWER DEVICED_OBJECT_PATH"/Power" +#define DEVICED_INTERFACE_POWER DEVICED_INTERFACE_NAME".power" +/* Low Power service: start/stop low power mode */ +#define DEVICED_PATH_LOWPOWER DEVICED_OBJECT_PATH"/LowPower" +#define DEVICED_INTERFACE_LOWPOWER DEVICED_INTERFACE_NAME".lowpower" +/* Reboot service: request reboot operation */ +#define DEVICED_PATH_REBOOT DEVICED_OBJECT_PATH"/Reboot" +#define DEVICED_INTERFACE_REBOOT DEVICED_INTERFACE_NAME".reboot" +/* Storage service: get storage size operatioins about storage */ +#define DEVICED_PATH_STORAGE DEVICED_OBJECT_PATH"/Storage" +#define DEVICED_INTERFACE_STORAGE DEVICED_INTERFACE_NAME".storage" +/* ODE service: request ode popup result operatioins about storage */ +#define DEVICED_PATH_SDE DEVICED_OBJECT_PATH"/Sde" +#define DEVICED_INTERFACE_SDE DEVICED_INTERFACE_NAME".sde" +#define DEVICED_PATH_ODE DEVICED_OBJECT_PATH"/Ode" +#define DEVICED_INTERFACE_ODE DEVICED_INTERFACE_NAME".ode" +/* Lowmem service: get critical low status operations about Lowmem */ +#define DEVICED_PATH_LOWMEM DEVICED_OBJECT_PATH"/Lowmem" +#define DEVICED_INTERFACE_LOWMEM DEVICED_INTERFACE_NAME".lowmem" +/* Poweroff service: get power off status operations about Poweroff */ +#define DEVICED_PATH_POWEROFF DEVICED_OBJECT_PATH"/PowerOff" +#define DEVICED_INTERFACE_POWEROFF DEVICED_INTERFACE_NAME".PowerOff" +/* Led service: play/stop led operations about led */ +#define DEVICED_PATH_LED DEVICED_OBJECT_PATH"/Led" +#define DEVICED_INTERFACE_LED DEVICED_INTERFACE_NAME".Led" +/* MMC service: mount/unmount/format mmc operations about mmc */ +#define DEVICED_PATH_MMC DEVICED_OBJECT_PATH"/Mmc" +#define DEVICED_INTERFACE_MMC DEVICED_INTERFACE_NAME".Mmc" +/* Process service: operations about process */ +#define DEVICED_PATH_PROCESS DEVICED_OBJECT_PATH"/Process" +#define DEVICED_INTERFACE_PROCESS DEVICED_INTERFACE_NAME".Process" +/* Key service: operations about key */ +#define DEVICED_PATH_KEY DEVICED_OBJECT_PATH"/Key" +#define DEVICED_INTERFACE_KEY DEVICED_INTERFACE_NAME".Key" +/* USB client service: change usb connection mode */ +#define DEVICED_PATH_USB DEVICED_OBJECT_PATH"/Usb" +#define DEVICED_INTERFACE_USB DEVICED_INTERFACE_NAME".Usb" +/* USB start/stop service: operations about usb start/stop */ +#define DEVICED_PATH_USB_CONTROL DEVICED_OBJECT_PATH"/UsbControl" +#define DEVICED_INTERFACE_USB_CONTROL DEVICED_INTERFACE_NAME".UsbControl" +/* USB host service: operations about usb start/stop */ +#define DEVICED_PATH_USBHOST DEVICED_OBJECT_PATH"/Usbhost" +#define DEVICED_INTERFACE_USBHOST DEVICED_INTERFACE_NAME".Usbhost" +/* Sysnoti service */ +#define DEVICED_PATH_SYSNOTI DEVICED_OBJECT_PATH"/SysNoti" +#define DEVICED_INTERFACE_SYSNOTI DEVICED_INTERFACE_NAME".SysNoti" +/* ExtCon service */ +#define DEVICED_PATH_EXTCON DEVICED_OBJECT_PATH"/ExtCon" +#define DEVICED_INTERFACE_EXTCON DEVICED_INTERFACE_NAME".ExtCon" +/* Battery service */ +#define DEVICED_PATH_BATTERY DEVICED_OBJECT_PATH"/Battery" +#define DEVICED_INTERFACE_BATTERY DEVICED_INTERFACE_NAME".Battery" +/* Time service */ +#define DEVICED_PATH_TIME DEVICED_OBJECT_PATH"/Time" +#define DEVICED_INTERFACE_TIME DEVICED_INTERFACE_NAME".Time" +/* IR service */ +#define DEVICED_PATH_IR DEVICED_OBJECT_PATH"/Ir" +#define DEVICED_INTERFACE_IR DEVICED_INTERFACE_NAME".ir" +/* USB_HOST_TEST service */ +#define DEVICED_PATH_USB_HOST_TEST DEVICED_OBJECT_PATH"/UsbHostTest" +#define DEVICED_INTERFACE_USB_HOST_TEST DEVICED_INTERFACE_NAME".UsbHostTest" + +/* HDMICEC service: status check about gpio */ +#define DEVICED_PATH_HDMICEC DEVICED_OBJECT_PATH"/HdmiCec" +#define DEVICED_INTERFACE_HDMICEC DEVICED_INTERFACE_NAME".HdmiCec" + +/* Tzip service: Archive file system */ +#define DEVICED_PATH_TZIP DEVICED_OBJECT_PATH"/Tzip" +#define DEVICED_INTERFACE_TZIP DEVICED_INTERFACE_NAME".Tzip" + + +/******************************************************************************* + * + * Storage daemon (storaged) + * + ******************************************************************************/ +#define STORAGED_BUS_NAME "org.tizen.system.storage" +#define STORAGED_OBJECT_PATH "/Org/Tizen/System/Storage" +#define STORAGED_INTERFACE_NAME STORAGED_BUS_NAME + +/* Block service */ +#define STORAGED_PATH_BLOCK STORAGED_OBJECT_PATH"/Block" +#define STORAGED_PATH_BLOCK_MANAGER STORAGED_PATH_BLOCK"/Manager" +#define STORAGED_INTERFACE_BLOCK_MANAGER STORAGED_INTERFACE_NAME".BlockManager" + +/* Storage service: get storage size operatioins about storage */ +#define STORAGED_PATH_STORAGE STORAGED_OBJECT_PATH"/Storage" +#define STORAGED_INTERFACE_STORAGE STORAGED_INTERFACE_NAME".storage" + +/* Lowmem service: get critical low status operations about Lowmem */ +#define STORAGED_PATH_LOWMEM STORAGED_OBJECT_PATH"/Lowmem" +#define STORAGED_INTERFACE_LOWMEM STORAGED_INTERFACE_NAME".lowmem" + + +/******************************************************************************* + * + * Vibrator daemon + * + ******************************************************************************/ +#define VIBRATOR_BUS_NAME "org.tizen.system.vibrator" +#define VIBRATOR_OBJECT_PATH "/Org/Tizen/System/Vibrator" +#define VIBRATOR_INTERFACE_NAME VIBRATOR_BUS_NAME +/* Core service: get/set device status operations about device */ +#define VIBRATOR_PATH_CORE VIBRATOR_OBJECT_PATH"/Core" +#define VIBRATOR_INTERFACE_CORE VIBRATOR_INTERFACE_NAME".core" + +#define VIBRATOR_PATH_HAPTIC VIBRATOR_OBJECT_PATH"/Haptic" +#define VIBRATOR_INTERFACE_HAPTIC VIBRATOR_INTERFACE_NAME".haptic" + +/* + * Resource daemon + */ +#define RESOURCED_BUS_NAME "org.tizen.resourced" +#define RESOURCED_OBJECT_PATH "/Org/Tizen/ResourceD" +#define RESOURCED_INTERFACE_NAME RESOURCED_BUS_NAME + +#define RESOURCED_PATH_PROCESS RESOURCED_OBJECT_PATH"/Process" +#define RESOURCED_INTERFACE_PROCESS RESOURCED_INTERFACE_NAME".process" +#define RESOURCED_METHOD_ACTIVE "Active" + +#define RESOURCED_PATH_FREEZER RESOURCED_OBJECT_PATH"/Freezer" +#define RESOURCED_INTERFACE_FREEZER RESOURCED_INTERFACE_NAME".freezer" + +#define RESOURCED_PATH_SLUGGISH RESOURCED_OBJECT_PATH"/Sluggish" +#define RESOURCED_INTERFACE_SLUGGISH RESOURCED_INTERFACE_NAME".sluggish" +#define RESOURCED_SIGNAL_SLUGGISH "SluggishDetected" + +#define RESOURCED_PATH_LOGGING RESOURCED_OBJECT_PATH"/Logging" +#define RESOURCED_INTERFACE_LOGGING RESOURCED_INTERFACE_NAME".logging" +/* + * Popup launcher + */ +#define POPUP_BUS_NAME "org.tizen.system.popup" +#define POPUP_OBJECT_PATH "/Org/Tizen/System/Popup" +#define POPUP_INTERFACE_NAME POPUP_BUS_NAME +/* LED */ +#define POPUP_PATH_LED POPUP_OBJECT_PATH"/Led" +#define POPUP_INTERFACE_LED POPUP_INTERFACE_NAME".Led" +/* System */ +#define POPUP_PATH_SYSTEM POPUP_OBJECT_PATH"/System" +#define POPUP_INTERFACE_SYSTEM POPUP_INTERFACE_NAME".System" +/* Notification */ +#define POPUP_PATH_NOTI POPUP_OBJECT_PATH"/Noti" +#define POPUP_INTERFACE_NOTI POPUP_INTERFACE_NAME".Noti" +/* Power key longpress */ +#define POPUP_PATH_POWERKEY POPUP_OBJECT_PATH"/Powerkey" +#define POPUP_INTERFACE_POWERKEY POPUP_INTERFACE_NAME".Powerkey" +/* Low battery */ +#define POPUP_PATH_LOWBAT POPUP_OBJECT_PATH"/Lowbat" +#define POPUP_INTERFACE_LOWBAT POPUP_INTERFACE_NAME".Lowbat" +/* Low memory */ +#define POPUP_PATH_LOWMEM POPUP_OBJECT_PATH"/Lowmem" +#define POPUP_INTERFACE_LOWMEM POPUP_INTERFACE_NAME".Lowmem" +/* MMC */ +#define POPUP_PATH_MMC POPUP_OBJECT_PATH"/Mmc" +#define POPUP_INTERFACE_MMC POPUP_INTERFACE_NAME".Mmc" +/* USB */ +#define POPUP_PATH_USB POPUP_OBJECT_PATH"/Usb" +#define POPUP_INTERFACE_USB POPUP_INTERFACE_NAME".Usb" +/* USB otg */ +#define POPUP_PATH_USBOTG POPUP_OBJECT_PATH"/Usbotg" +#define POPUP_INTERFACE_USBOTG POPUP_INTERFACE_NAME".Usbotg" +/* USB host */ +#define POPUP_PATH_USBHOST POPUP_OBJECT_PATH"/Usbhost" +#define POPUP_INTERFACE_USBHOST POPUP_INTERFACE_NAME".Usbhost" +/* System */ +#define POPUP_PATH_SYSTEM POPUP_OBJECT_PATH"/System" +#define POPUP_INTERFACE_SYSTEM POPUP_INTERFACE_NAME".System" +/* Overheat */ +#define POPUP_PATH_OVERHEAT POPUP_OBJECT_PATH"/Overheat" +#define POPUP_INTERFACE_OVERHEAT POPUP_INTERFACE_NAME".Overheat" +/* Crash */ +#define POPUP_PATH_CRASH POPUP_OBJECT_PATH"/Crash" +#define POPUP_INTERFACE_CRASH POPUP_INTERFACE_NAME".Crash" +/* Servant */ +#define POPUP_PATH_SERVANT POPUP_OBJECT_PATH"/Servant" +#define POPUP_IFACE_SERVANT POPUP_INTERFACE_NAME".Servant" + +#define POPUP_PATH_APP POPUP_OBJECT_PATH"/Apps" +#define POPUP_IFACE_APP POPUP_BUS_NAME".Apps" + +#define POPUP_METHOD_LAUNCH "PopupLaunch" +#define POPUP_METHOD_TERMINATE "AppTerminateByPid" +#define POPUP_KEY_CONTENT "_SYSPOPUP_CONTENT_" + +/* + * Crash daemon + */ +#define CRASHD_BUS_NAME "org.tizen.system.crashd" +#define CRASHD_OBJECT_PATH "/Org/Tizen/System/CrashD" +#define CRASHD_INTERFACE_NAME CRASHD_BUS_NAME + +#define CRASHD_PATH_CRASH CRASHD_OBJECT_PATH"/Crash" +#define CRASHD_INTERFACE_CRASH CRASHD_INTERFACE_NAME".Crash" + +/* + * Device Manager Policy Popup + */ +#define DEVICEMANAGER_BUS_NAME "org.tizen.DevicePolicyManager" +#define DEVICEMANAGER_OBJECT_PATH "/org/tizen/DevicePolicyManager" +#define DEVICEMANAGER_INTERFACE_NAME DEVICEMANAGER_BUS_NAME + +#define DEVICEMANAGER_PATH_POPUP DEVICEMANAGER_OBJECT_PATH"/Syspopup" +#define DEVICEMANAGER_INTERFACE_POPUP DEVICEMANAGER_INTERFACE_NAME".Syspopup" + + +/***************************************************************/ +/* Experimental for Specific device - contact to deviced owner */ +/***************************************************************/ + +/* Hall service: get hall status operations about hall */ +#define DEVICED_PATH_HALL DEVICED_OBJECT_PATH"/Hall" +#define DEVICED_INTERFACE_HALL DEVICED_INTERFACE_NAME".hall" +/* Cpu service: operations about cpu */ +#define DEVICED_PATH_CPU DEVICED_OBJECT_PATH"/Cpu" +#define DEVICED_INTERFACE_CPU DEVICED_INTERFACE_NAME".Cpu" +/* PmQos service: operations about pmqos */ +#define DEVICED_PATH_PMQOS DEVICED_OBJECT_PATH"/PmQos" +#define DEVICED_INTERFACE_PMQOS DEVICED_INTERFACE_NAME".PmQos" +/* Apps service */ +#define DEVICED_PATH_APPS DEVICED_OBJECT_PATH"/Apps" +#define DEVICED_INTERFACE_APPS DEVICED_INTERFACE_NAME".Apps" +/* GPIO service: status check about gpio */ +#define DEVICED_PATH_GPIO DEVICED_OBJECT_PATH"/Gpio" +#define DEVICED_INTERFACE_GPIO DEVICED_INTERFACE_NAME".Gpio" +/* Board service */ +#define DEVICED_PATH_BOARD DEVICED_OBJECT_PATH"/Board" +#define DEVICED_INTERFACE_BOARD DEVICED_INTERFACE_NAME".Board" +/* Csa service */ +#define DEVICED_PATH_CSA DEVICED_OBJECT_PATH"/Csa" +#define DEVICED_INTERFACE_CSA DEVICED_INTERFACE_NAME".Csa" +/* dump service */ +#define DUMP_SERVICE_BUS_NAME "org.tizen.system.dumpservice" +#define DUMP_SERVICE_OBJECT_PATH "/Org/Tizen/System/DumpService" +#define DUMP_SERVICE_INTERFACE_NAME DUMP_SERVICE_BUS_NAME +/* Coord daemon */ +#define COORD_BUS_NAME "org.tizen.system.coord" +#define COORD_OBJECT_PATH "/Org/Tizen/System/Coord" +#define COORD_INTERFACE_NAME COORD_BUS_NAME +#define COORD_PATH_AUTOBRIGHTNESS COORD_OBJECT_PATH"/Autobrightness" +#define COORD_INTERFACE_AUTOBRIGHTNESS COORD_INTERFACE_NAME".autobrightness" + +/* LED */ +#define POPUP_PATH_LED POPUP_OBJECT_PATH"/Led" +#define POPUP_INTERFACE_LED POPUP_INTERFACE_NAME".Led" +/* ODE */ +#define POPUP_PATH_ODE POPUP_OBJECT_PATH"/Ode" +#define POPUP_INTERFACE_ODE POPUP_INTERFACE_NAME".Ode" +/* Battery */ +#define POPUP_PATH_BATTERY POPUP_OBJECT_PATH"/Battery" +#define POPUP_INTERFACE_BATTERY POPUP_INTERFACE_NAME".Battery" +#define POPUP_METHOD_SCREENOFF_TTS "ScreenOffTts" +/* Overheat Timer*/ +#define POPUP_OVERHEAT_PATH POPUP_OBJECT_PATH"/Overheat" +#define POPUP_OVERHEAT_INTERFACE POPUP_INTERFACE_NAME".Overheat" + +/***********************************************/ +/* End of the Experimental for Specific device */ +/***********************************************/ + + + +typedef struct { + const unsigned char *data; + int size; +} dbus_byte; + +GVariant *dbus_handle_method_sync_with_reply_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *var); + +GVariant *dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path, const char *iface, const char *method, GVariant *var, int timeout); + +/* fd */ +gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size); + +GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply(const char *dest, const char *path, + const char *iface, const char *method, + const char *signature, const char *param[], + int *in_fdlist, int in_size, + int **out_fdlist, int *out_size); +GVariant *dbus_handle_method_with_unix_fd_list_sync_with_reply_var(const char *dest, const char *path, + const char *iface, const char *method, + GVariant *param, + int *in_fdlist, int in_size, + int **out_fdlist, int *out_size); + +int dbus_handle_method_sync(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, const char *param[]); + +int dbus_handle_method_sync_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *param); + +int dbus_handle_method_sync_timeout(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, const char *param[], int timeout); + +int dbus_handle_method_sync_pairs(const char *dest, const char *path, + const char *interface, const char *method, + int num, va_list args); +int dbus_handle_method_async_pairs(const char *dest, const char *path, + const char *interface, const char *method, + int num, va_list args); +int dbus_handle_method_async(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, const char *param[]); + +int dbus_handle_method_async_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *param); + +typedef void (*dbus_pending_cb)(GVariant *var, void *user_data, GError *err); + +int dbus_handle_method_async_with_reply(const char *dest, + const char *path, + const char *iface, + const char *method, + const char *signature, + const char *param[], + dbus_pending_cb cb, + int timeout_msec, + void *data); + + +int dbus_handle_method_async_with_reply_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + dbus_pending_cb cb, + int timeout_msec, + void *data); + +int check_systemd_active(void); + +/** + * @brief Dbus handler which is used to register and call methods + + * @since_tizen 4.0 + */ +typedef void *dbus_handle_h; + +/** + * @brief Dbus method handler which is used to unregister dbus methods + * @since_tizen 4.0 + */ +typedef void *dbus_object_handle_h; + +/** + * @brief Structure which contains the dbus method name and callback function. + * @since_tizen 4.0 + */ +typedef struct { + const char *member; + const char *signature_in; + const char *signature_out; + GVariant *(*func)(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data); +} dbus_method_s; + +/** + * @brief Structure which contains the dbus interface information and its methods.i + * @since_tizen 4.0 + */ +typedef struct { + dbus_object_handle_h oh; + const char *name; + const dbus_method_s *methods; + int nr_methods; +} dbus_interface_u; + +#define dh_get_param_from_var(gvar, signature, ...) ((g_strcmp0(signature, g_variant_get_type_string(gvar)) == 0) ? g_variant_get(gvar, signature, __VA_ARGS__), TRUE : FALSE) + +#define dbus_handle_new_g_variant_tuple() g_variant_new_tuple(NULL, 0) + +/** + * @brief Callback function which is called when the user data needs to be released. + * @since_tizen 4.0 + */ +typedef void (*destroy_notified)(void *data); + +typedef struct { + dbus_pending_cb func; + void *data; +} pending_call_data; + +int dbus_handle_request_bus_name(dbus_handle_h handle, const char *bus_name, GBusNameAcquiredCallback acquired_handler, GBusNameLostCallback lost_handler); + +dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv); + +int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface); +int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path); + +int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u); +int dbus_handle_register_dbus_object_all(dbus_handle_h handle); + +guint subscribe_dbus_signal(dbus_handle_h handle, const char *path, const char *iface, const char *name, GDBusSignalCallback cb, void *data, destroy_notified free_func); +void unsubscribe_dbus_signal(dbus_handle_h handle, guint id); + +GVariant *dbus_handle_make_simple_array(const char *sig, int *param); + +int dbus_handle_broadcast_dbus_signal(const char *path, const char *iface, const char *name, const char *signature, const char *param[]); +int dbus_handle_broadcast_dbus_signal_var(const char *path, const char *iface, const char *name, GVariant *param); + +typedef struct +{ + guint pid; + guint uid; + gchar *unique_name; + gchar *sec_label; +} GDBusCredentials; + +int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender); +int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender); +int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds); +int dbus_handle_watch_name(const char *name, GBusNameAppearedCallback name_appeared_handler, GBusNameVanishedCallback name_vanished_handler, void *user_data, GDestroyNotify user_data_free_func); +void dbus_handle_unwatch_name(guint id); +dbus_handle_h dbus_handle_init(GBusType type, const char* bus_name, GBusNameAcquiredCallback acquired_handler, GBusNameLostCallback lost_handler); +char** dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name); +void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name); + +#endif diff --git a/src/libgdbus/libgdbus.pc.in b/src/libgdbus/libgdbus.pc.in new file mode 100644 index 0000000..58569e6 --- /dev/null +++ b/src/libgdbus/libgdbus.pc.in @@ -0,0 +1,17 @@ +# Package Information for pkg-config +# +# Copyright (c) 2016 Samsung Electronics Co., Ltd. +# All rights reserved. +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libgdbus +Description: Dbus library +Version: @PACKAGE_VERSION@ +Requires.private: @LIBGDBUS_PC_REQUIRES@ +Cflags: @LIBGDBUS_PC_CFLAGS@ +Libs: @LIBGDBUS_PC_LIBS@ diff --git a/src/shared/log-macro.h b/src/shared/log-macro.h new file mode 100644 index 0000000..8532b37 --- /dev/null +++ b/src/shared/log-macro.h @@ -0,0 +1,51 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * 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 __LOG_MACRO_H__ +#define __LOG_MACRO_H__ + +#ifdef ENABLE_DLOG +#include +#define _D(fmt, arg...) \ + do { SLOGD(fmt, ##arg); } while (0) +#define _I(fmt, arg...) \ + do { SLOGI(fmt, ##arg); } while (0) +#define _W(fmt, arg...) \ + do { SLOGW(fmt, ##arg); } while (0) +#define _E(fmt, arg...) \ + do { SLOGE(fmt, ##arg); } while (0) +#define _SD(fmt, arg...) \ + do { SECURE_SLOGD(fmt, ##arg); } while (0) +#define _SI(fmt, arg...) \ + do { SECURE_SLOGI(fmt, ##arg); } while (0) +#define _SW(fmt, arg...) \ + do { SECURE_SLOGW(fmt, ##arg); } while (0) +#define _SE(fmt, arg...) \ + do { SECURE_SLOGE(fmt, ##arg); } while (0) +#else +#define _D(...) do { } while (0) +#define _I(...) do { } while (0) +#define _W(...) do { } while (0) +#define _E(...) do { } while (0) +#define _SD(...) do { } while (0) +#define _SI(...) do { } while (0) +#define _SW(...) do { } while (0) +#define _SE(...) do { } while (0) +#endif +#endif diff --git a/src/shared/log.h b/src/shared/log.h new file mode 100644 index 0000000..4e9b338 --- /dev/null +++ b/src/shared/log.h @@ -0,0 +1,30 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * 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 __LOG_H__ +#define __LOG_H__ + +#ifdef ENABLE_LIBDEVICED_DLOG +#define ENABLE_DLOG +#endif + +#define LOG_TAG "LIBSYSTEM" +#include "shared/log-macro.h" + +#endif -- 2.7.4 From 03c783d710add763641553c75e056fe8d90ea54c Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 26 Mar 2018 17:36:40 +0900 Subject: [PATCH 3/5] Remove unused Requires Change-Id: Id57b7a4b01698fcc2aeeaba233e96c650eec9e7a Signed-off-by: pr.jung --- packaging/libsyscommon.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/libsyscommon.spec b/packaging/libsyscommon.spec index 6cef3e8..45c24c5 100644 --- a/packaging/libsyscommon.spec +++ b/packaging/libsyscommon.spec @@ -38,7 +38,6 @@ License: Apache-2.0 Requires: libgdbus = %{version} Requires: pkgconfig(gio-2.0) Requires: pkgconfig(gio-unix-2.0) -Requires: pkgconfig(dbus-1) %description -n libgdbus-devel Development header files for dbus library. -- 2.7.4 From 18051160ef985c5c0f4ac735bf9a1b7fa5eb1625 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Wed, 4 Apr 2018 21:31:56 +0900 Subject: [PATCH 4/5] Remove dbus_handle_init to solve timimg issue refactor dbus_handle_init to two parts in deviced, storaged and feedbackd. It's to solve timing issue in deviced by AddPoweroffWait method. Change-Id: I32246f4667dc29447037636ae9b8bf02593e36fe Signed-off-by: lokilee73 --- src/libgdbus/dbus-system.c | 53 ++++++++++++---------------------------------- src/libgdbus/dbus-system.h | 3 +-- 2 files changed, 15 insertions(+), 41 deletions(-) mode change 100644 => 100755 src/libgdbus/dbus-system.c mode change 100644 => 100755 src/libgdbus/dbus-system.h diff --git a/src/libgdbus/dbus-system.c b/src/libgdbus/dbus-system.c old mode 100644 new mode 100755 index 22df703..fa377a3 --- a/src/libgdbus/dbus-system.c +++ b/src/libgdbus/dbus-system.c @@ -304,18 +304,25 @@ err: dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv) { dbus_handle_s *dh = NULL; + int i; if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { _E("Wrong bus_type %d\n", bus_type); return dh; } - /* private */ - if (priv) - dh = _dbus_handle_get_connection_private(bus_type); - /* shared */ - else - dh = _dbus_handle_get_connection(bus_type); + for (i = 0 ; i < 3; ++i) { + /* private */ + if (priv) + dh = _dbus_handle_get_connection_private(bus_type); + /* shared */ + else + dh = _dbus_handle_get_connection(bus_type); + + if (dh) + break; + usleep(5000); + } return dh; } @@ -2636,7 +2643,7 @@ char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name) return strv; } -void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name) +void dbus_handle_check_owner_name(dbus_handle_h handle, const char *owner_name) { dcl_dbus_handle(); char exe_name[PATH_MAX]; @@ -2667,35 +2674,3 @@ void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name) g_strfreev(strv); } - -dbus_handle_h dbus_handle_init(GBusType type, - const char* bus_name, - GBusNameAcquiredCallback acquired_handler, - GBusNameLostCallback lost_handler) -{ - dbus_handle_h handle = NULL; - int i, ret = 0; - - if (!bus_name) { - _E("Wrong bus name"); - return NULL; - } - - // todo: do we need retry ? - booting time - for (i = 0 ; i < 3; ++i) { - handle = dbus_handle_get_connection(type, FALSE); - if (handle) - break; - usleep(5000); - } - ret = dbus_handle_request_bus_name(handle, bus_name, acquired_handler, lost_handler); - if (ret <= 0) - goto out; - - dbush_handle_check_owner_name(NULL, bus_name); - - return handle; - -out: - return NULL; -} diff --git a/src/libgdbus/dbus-system.h b/src/libgdbus/dbus-system.h old mode 100644 new mode 100755 index 42f2f8f..126e12a --- a/src/libgdbus/dbus-system.h +++ b/src/libgdbus/dbus-system.h @@ -490,8 +490,7 @@ int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender); int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds); int dbus_handle_watch_name(const char *name, GBusNameAppearedCallback name_appeared_handler, GBusNameVanishedCallback name_vanished_handler, void *user_data, GDestroyNotify user_data_free_func); void dbus_handle_unwatch_name(guint id); -dbus_handle_h dbus_handle_init(GBusType type, const char* bus_name, GBusNameAcquiredCallback acquired_handler, GBusNameLostCallback lost_handler); char** dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name); -void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name); +void dbus_handle_check_owner_name(dbus_handle_h handle, const char *owner_name); #endif -- 2.7.4 From 04f61bd50b4751c7a8ca8d6390110003099b2398 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Fri, 30 Mar 2018 14:09:58 +0900 Subject: [PATCH 5/5] make: change to cmake Change-Id: I57979761fed3eeef223a236308c8d8e529fb5b37 Signed-off-by: sanghyeok.oh --- CMakeLists.txt | 5 ++ Makefile.am | 2 - autogen.sh | 45 ----------------- configure.ac | 120 -------------------------------------------- packaging/libsyscommon.spec | 25 ++------- src/libgdbus/CMakeLists.txt | 55 ++++++++++++++++++++ src/libgdbus/libgdbus.pc.in | 16 +++--- 7 files changed, 72 insertions(+), 196 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Makefile.am delete mode 100755 autogen.sh delete mode 100644 configure.ac create mode 100644 src/libgdbus/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..10850df --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(libsyscommon C) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) +ADD_SUBDIRECTORY(src/libgdbus) \ No newline at end of file diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index dfa49b2..0000000 --- a/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -AUTOMAKE_OPTIONS = foreign -SUBDIRS = src diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 3825cb5..0000000 --- a/autogen.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -set -e - -opt="$1" - -if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then - # This part is allowed to fail - cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ - chmod +x .git/hooks/pre-commit && \ - echo "Activated pre-commit hook." || : -fi - -# README and INSTALL are required by automake, but may be deleted by -# clean up rules. to get automake to work, simply touch these here, -# they will be regenerated from their corresponding *.in files by -# ./configure anyway. -touch README INSTALL - -# make sure m4 dir exist -mkdir -p m4 - -autoreconf --force --install --verbose || exit $? - -if [ "x$opt" = "xc" ]; then - set -x - ./configure $args - make clean > /dev/null -elif [ "x$opt" = "xd" ]; then - set -x - ./configure CFLAGS='-g -O0 -ftrapv' $args - make clean > /dev/null -elif [ "x$opt" = "xg" ]; then - set -x - ./configure CFLAGS='-g -Og -ftrapv' $args - make clean > /dev/null -elif [ "x$opt" = "xl" ]; then - set -x - ./configure CC=clang CFLAGS='-g -O0 -ftrapv' $args - make clean > /dev/null -elif [ "x$opt" = "xs" ]; then - set -x - scan-build ./configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args - scan-build make -fi diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 0d033da..0000000 --- a/configure.ac +++ /dev/null @@ -1,120 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_PREREQ([2.68]) -AC_INIT([libsystem], [4.1], [walyong.cho@samsung.com]) - -dnl AC_CONFIG_MACRO_DIRS([m4]) -AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_HEADERS([config.h]) - -AC_USE_SYSTEM_EXTENSIONS -AC_SYS_LARGEFILE -AC_PREFIX_DEFAULT([/usr]) -AM_INIT_AUTOMAKE([foreign subdir-objects]) - -LT_PREREQ(2.2) -LT_INIT([disable-static]) - -# Checks for programs. -AC_PROG_CXX -AC_PROG_AWK -AC_PROG_CC -AC_PROG_CPP -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_MAKE_SET -AC_PROG_RANLIB - -# Checks for libraries. -# FIXME: Replace `main' with a function in `-lrt': -AC_CHECK_LIB([rt], [main]) - -# Checks for header files. -AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h mntent.h stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_CHECK_HEADER_STDBOOL -AC_C_INLINE -AC_TYPE_INT32_T -AC_TYPE_INT64_T -AC_TYPE_MODE_T -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_TYPE_SSIZE_T -AC_TYPE_UINT32_T -AC_TYPE_UINT64_T - -# Checks for library functions. -AC_FUNC_FORK -AC_FUNC_GETMNTENT -AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK -AC_FUNC_MKTIME -AC_FUNC_REALLOC -AC_CHECK_FUNCS([dup2 getmntent gettimeofday localtime_r memset mkdir rmdir strchr strcspn strdup strndup strrchr strspn]) - -AC_CHECK_TOOL(GPERF, gperf) -if test -z "$GPERF" ; then - AC_MSG_ERROR([*** gperf not found]) -fi - -# ------------------------------------------------------------------------------ -our_cflags=" \ - -g -O2 \ - -Werror \ - -fpie" - -our_ldflags=" \ - -Wl,--as-needed \ - -Wl,--no-undefined \ - -Wl,--gc-sections \ - -Wl,-z,relro \ - -Wl,-z,now \ - -pie" - -our_cflags=$(echo $our_cflags |sed 's/\t/ /g' | sed 's/ / /g') -our_ldflags=$(echo $our_ldflags | sed 's/\t/ /g' | sed 's/ / /g') - -AC_SUBST([OUR_CFLAGS], "$our_cflags") -AC_SUBST([OUR_LDFLAGS], "$our_ldflags") - -# ------------------------------------------------------------------------------ -PKG_CHECK_MODULES(GLIB, [glib-2.0]) -PKG_CHECK_MODULES(GIO, [gio-2.0]) -PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0]) - -# ------------------------------------------------------------------------------ -AC_SUBST([LIBGDBUS_PC_REQUIRES], "libgdbus") -AC_SUBST([LIBGDBUS_PC_CFLAGS], "") -AC_SUBST([LIBGDBUS_PC_LIBS], "-L${libdir} -lgdbus") - -AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${DBUS_REQUIRES}") -AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${DBUS_CFLAGS}") -AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${DBUS_LIBS}") - -AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${GIO_REQUIRES}") -AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${GIO_CFLAGS}") -AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${GIO_LIBS}") - -AC_SUBST([LIBGDBUS_PC_REQUIRES], "${LIBGDBUS_PC_REQUIRES} ${GIO_UNIX_REQUIRES}") -AC_SUBST([LIBGDBUS_PC_CFLAGS], "${LIBGDBUS_PC_CFLAGS} ${GIO_UNIX_CFLAGS}") -AC_SUBST([LIBGDBUS_PC_LIBS], "${LIBGDBUS_PC_LIBS} ${GIO_UNIX_LIBS}") - -# ------------------------------------------------------------------------------ -AC_CONFIG_FILES([Makefile - src/Makefile]) -AC_OUTPUT -AC_MSG_RESULT([ - $PACKAGE_NAME $VERSION - - prefix: ${prefix} - rootprefix: ${with_rootprefix} - datarootdir: ${datarootdir} - lib dir: ${libdir} - rootlib dir: ${with_rootlibdir} - - OUR CFLAGS: ${OUR_CFLAGS} - CFLAGS: ${CFLAGS} - OUR LDFLAGS: ${OUR_LDFLAGS} - LDFLAGS: ${LDFLAGS} -]) diff --git a/packaging/libsyscommon.spec b/packaging/libsyscommon.spec index 45c24c5..3dc79ff 100644 --- a/packaging/libsyscommon.spec +++ b/packaging/libsyscommon.spec @@ -9,13 +9,10 @@ Source: %{name}-%{version}.tar.gz Source1001: %{name}.manifest %endif -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: libtool BuildRequires: pkgconfig(glib-2.0) >= 2.44 BuildRequires: pkgconfig(gio-2.0) >= 2.44 BuildRequires: pkgconfig(gio-unix-2.0) -BuildRequires: gperf +BuildRequires: cmake Requires: /bin/cp @@ -26,14 +23,14 @@ Requires(postun): /sbin/ldconfig System utility libraries. %package -n libgdbus -Summary: Dbus library +Summary: Dbus library License: Apache-2.0 %description -n libgdbus Internal dbus library %package -n libgdbus-devel -Summary: Header files for dbus library +Summary: Header files for dbus library License: Apache-2.0 Requires: libgdbus = %{version} Requires: pkgconfig(gio-2.0) @@ -49,30 +46,16 @@ cp %{SOURCE1001} . %endif %build -%if 0%{?debug_enable} -export CFLAGS=$(echo $CFLAGS | sed -e 's/^-g / /g' | sed -e 's/ -g / /g') -export CFLAGS=$(echo $CFLAGS | sed -e 's/^-O[0-9] / /g' | sed -e 's/ $-O[0-9] / /g') -export CFLAGS=$(echo $CFLAGS | sed -e 's/-Wp,-D_FORTIFY_SOURCE=2 / /g') -export CFLAGS="-O0 -g $CFLAGS" -%endif - -./autogen.sh -%configure - +%cmake . make %{?_smp_mflags} %install %make_install -rm -f %{buildroot}%{_libdir}/*.la - # make sure debugsources.list exist, it used by rpm macro in %file # section. touch debugsources.list -%check -make check - %post /sbin/ldconfig diff --git a/src/libgdbus/CMakeLists.txt b/src/libgdbus/CMakeLists.txt new file mode 100644 index 0000000..327ea2b --- /dev/null +++ b/src/libgdbus/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(libgdbus C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}/bin") +SET(LIBDIR ${LIB_INSTALL_DIR}) +SET(INCLUDEDIR "${PREFIX}/include") +SET(VERSION 4.1) + +SET(libgdbus_SRCS + dbus-system.c +) +SET(HEADERS + dbus-system.h +) + +# CHECK PKG +INCLUDE(FindPkgConfig) +pkg_check_modules(gdbus REQUIRED + glib-2.0 + gio-2.0 + gio-unix-2.0) + +FOREACH(flag ${gdbus_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +# LIBRARY +ADD_LIBRARY(${PROJECT_NAME} SHARED ${libgdbus_SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${gdbus_LDFLAGS} "-ldl" pthread) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fPIC") +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME gdbus) + +# INSTALL +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) + +# CONGIFURE FILE +FOREACH(flag ${gdbus_INCLUDE_DIRS}) + SET(GDBUS_INCLUDEDIR "${GDBUS_INCLUDEDIR} -I${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${gdbus_LIBRARIES}) + SET(GDBUS_LIBS "${GDBUS_LIBS} -l${flag}") +ENDFOREACH(flag) + +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +# HEADER +FOREACH(hfile ${HEADERS}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/${PROJECT_NAME}) +ENDFOREACH(hfile) diff --git a/src/libgdbus/libgdbus.pc.in b/src/libgdbus/libgdbus.pc.in index 58569e6..5616aac 100644 --- a/src/libgdbus/libgdbus.pc.in +++ b/src/libgdbus/libgdbus.pc.in @@ -4,14 +4,14 @@ # All rights reserved. # -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ Name: libgdbus Description: Dbus library -Version: @PACKAGE_VERSION@ -Requires.private: @LIBGDBUS_PC_REQUIRES@ -Cflags: @LIBGDBUS_PC_CFLAGS@ -Libs: @LIBGDBUS_PC_LIBS@ +Version: @VERSION@ +Requires.private: libgdbus +Cflags: -I${includedir} @GDBUS_INCLUDEDIR@ +Libs: -L${libdir} -lgdbus @GDBUS_LIBS@ -- 2.7.4