From: Hyotaek Shim Date: Tue, 9 Mar 2021 04:24:11 +0000 (+0900) Subject: Rearrange header and source files X-Git-Tag: submit/tizen/20210319.090004~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=41bb90025fbe75dbc13f6bfc926109e1a337f591;p=platform%2Fcore%2Fsystem%2Flibsyscommon.git Rearrange header and source files Change-Id: I7cb9725a5be1ac4ead7cac73d50203f413f669cf Signed-off-by: Hyotaek Shim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d314ee5..e16516d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,16 +12,14 @@ SET(INCLUDEDIR "${PREFIX}/include") SET(VERSION 4.1) SET(libsyscommon_SRCS - src/libgdbus/dbus-system.c - src/libgdbus/dbus-systemd.c - src/libsystemd/systemd-state.c + src/libgdbus/libgdbus.c + src/libsystemd/libsystemd.c src/libcommon/ini-parser.c ) SET(HEADERS - src/libgdbus/dbus-system.h - src/libgdbus/dbus-system-iface.h - src/libgdbus/dbus-systemd.h - src/libsystemd/systemd-state.h + src/libgdbus/libgdbus.h + src/libgdbus/dbus-iface-system.h + src/libsystemd/libsystemd.h src/libcommon/list.h src/libcommon/ini-parser.h src/libcommon/file.h diff --git a/src/libgdbus/dbus-iface-system.h b/src/libgdbus/dbus-iface-system.h new file mode 100644 index 0000000..e65384a --- /dev/null +++ b/src/libgdbus/dbus-iface-system.h @@ -0,0 +1,341 @@ +/* + * libsyscommon + * + * Copyright (c) 2019 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_SYSTEM_IFACE_H__ +#define __DBUS_SYSTEM_IFACE_H__ + +/* + * 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" + +/******************************************************************************* + * + * 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" +/* 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" +/* Poweroff service: request power off operation or get power off status operations about Poweroff(signal) */ +#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" +/* 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" + +/* Touch service */ +#define DEVICED_PATH_TOUCH DEVICED_OBJECT_PATH"/Touch" +#define DEVICED_INTERFACE_TOUCH DEVICED_INTERFACE_NAME".touch" + +/* Thermal service: operatioins about temperature */ +#define DEVICED_PATH_TEMPERATURE DEVICED_OBJECT_PATH"/Temperature" +#define DEVICED_INTERFACE_TEMPERATURE DEVICED_INTERFACE_NAME".temperature" + +/* Input service: To broadcast key input values */ +#define DEVICED_PATH_INPUT DEVICED_OBJECT_PATH"/Input" +#define DEVICED_INTERFACE_INPUT DEVICED_INTERFACE_NAME".input" + +/******************************************************************************* + * + * 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" + +/* + * Pass daemon + */ +#define PASS_BUS_NAME "org.tizen.system.pass" +#define PASS_OBJECT_PATH "/Org/Tizen/System/Pass" +#define PASS_INTERFACE_NAME PASS_BUS_NAME + +#define PASS_PATH_PMQOS PASS_OBJECT_PATH"/Pmqos" +#define PASS_INTERFACE_PMQOS PASS_INTERFACE_NAME".pmqos" + +#define PASS_METHOD_SET_SCENARIO "SetScenario" + +/***************************************************************/ +/* 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 */ +/***********************************************/ + + +#endif \ No newline at end of file diff --git a/src/libgdbus/dbus-system-iface.h b/src/libgdbus/dbus-system-iface.h deleted file mode 100644 index e65384a..0000000 --- a/src/libgdbus/dbus-system-iface.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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_SYSTEM_IFACE_H__ -#define __DBUS_SYSTEM_IFACE_H__ - -/* - * 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" - -/******************************************************************************* - * - * 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" -/* 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" -/* Poweroff service: request power off operation or get power off status operations about Poweroff(signal) */ -#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" -/* 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" - -/* Touch service */ -#define DEVICED_PATH_TOUCH DEVICED_OBJECT_PATH"/Touch" -#define DEVICED_INTERFACE_TOUCH DEVICED_INTERFACE_NAME".touch" - -/* Thermal service: operatioins about temperature */ -#define DEVICED_PATH_TEMPERATURE DEVICED_OBJECT_PATH"/Temperature" -#define DEVICED_INTERFACE_TEMPERATURE DEVICED_INTERFACE_NAME".temperature" - -/* Input service: To broadcast key input values */ -#define DEVICED_PATH_INPUT DEVICED_OBJECT_PATH"/Input" -#define DEVICED_INTERFACE_INPUT DEVICED_INTERFACE_NAME".input" - -/******************************************************************************* - * - * 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" - -/* - * Pass daemon - */ -#define PASS_BUS_NAME "org.tizen.system.pass" -#define PASS_OBJECT_PATH "/Org/Tizen/System/Pass" -#define PASS_INTERFACE_NAME PASS_BUS_NAME - -#define PASS_PATH_PMQOS PASS_OBJECT_PATH"/Pmqos" -#define PASS_INTERFACE_PMQOS PASS_INTERFACE_NAME".pmqos" - -#define PASS_METHOD_SET_SCENARIO "SetScenario" - -/***************************************************************/ -/* 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 */ -/***********************************************/ - - -#endif \ No newline at end of file diff --git a/src/libgdbus/dbus-system.c b/src/libgdbus/dbus-system.c deleted file mode 100644 index 45b0874..0000000 --- a/src/libgdbus/dbus-system.c +++ /dev/null @@ -1,2639 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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) - -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); - -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); - if (!dh->conn) { - dbus_handle_unlock(dh); - return NULL; - } - dh->priv = FALSE; - dh->bus_type = bus_type; - } - - 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; - 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; - } - - 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; -} - -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 is null"); - 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; -} - -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); -} - -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); -} - -static void _signal_reply_sync_cb(GDBusConnection *conn, - const gchar *sender, - const gchar *path, - const gchar *iface, - const gchar *name, - GVariant *param, - gpointer data) -{ - sig_ctx *ctx = data; - if (!ctx) { - _E("user data is null"); - assert(0); - } - - ctx->param = g_variant_ref(param); - ctx->quit_reason = CTX_QUIT_NORMAL; - - if (ctx->timeout_src) { - g_source_destroy(ctx->timeout_src); - ctx->timeout_src = NULL; - } - g_main_loop_quit(ctx->loop); -} - -sig_ctx *dbus_handle_new_signal_ctx(void) -{ - sig_ctx *ctx; - - ctx = (sig_ctx *)malloc(sizeof(sig_ctx)); - if (!ctx) { - _E("failed to alloc mem"); - return NULL; - } - - ctx->sig_id = 0; - - ctx->context = g_main_context_new(); - if (!ctx->context) { - _E("failed to alloc context"); - free(ctx); - return NULL; - } - ctx->loop = g_main_loop_new(ctx->context, FALSE); - if (!ctx->loop) { - _E("failed to alloc main loop"); - g_main_context_unref(ctx->context); - free(ctx); - return NULL; - } - ctx->timeout_src = NULL; - ctx->param = NULL; - ctx->quit_reason = CTX_QUIT_UNKNOWN; - ctx->user_data = NULL; - - return ctx; -} - -void dbus_handle_free_signal_ctx(sig_ctx *ctx) -{ - if (!ctx) - return ; - - if (ctx->param) { - g_variant_unref(ctx->param); - ctx->param = NULL; - } - if (ctx->sig_id) { - unsubscribe_dbus_signal(NULL, ctx->sig_id); - ctx->sig_id = 0; - } - if (ctx->timeout_src) { - g_source_destroy(ctx->timeout_src); - ctx->timeout_src = NULL; - } - if (ctx->context) { - g_main_context_pop_thread_default(ctx->context); - g_main_context_unref(ctx->context); - ctx->context = NULL; - } - if (ctx->loop) { - g_main_loop_unref(ctx->loop); - ctx->loop = NULL; - } - free(ctx); -} - -static gboolean _cb_ctx_timeout(gpointer user_data) -{ - sig_ctx *ctx = user_data; - - if (!ctx) { - _E("user_data is null"); - return FALSE; - } - - ctx->quit_reason = CTX_QUIT_TIMEOUT; - /* if cb return FALSE, source will be destroyed */ - ctx->timeout_src = NULL; - - unsubscribe_dbus_signal(NULL, ctx->sig_id); - ctx->sig_id = 0; - - g_main_loop_quit(ctx->loop); - - return FALSE; -} - -#define CTX_MAX_TIMEOUT 25000 - -int dbus_handle_signal_ctx_add_timeout(sig_ctx *ctx, int timeout_msec) -{ - GSource *src = NULL; - - if (!ctx) - return -EINVAL; - if (timeout_msec < -1) - return -EINVAL; - - if (timeout_msec == -1 || timeout_msec >= CTX_MAX_TIMEOUT) - timeout_msec = CTX_MAX_TIMEOUT; - - src = g_timeout_source_new(timeout_msec); - if (!src) - return -ENOMEM; - - g_source_set_callback(src, _cb_ctx_timeout, ctx, NULL); - g_source_attach(src, ctx->context); - g_source_unref(src); - - ctx->timeout_src = src; - - return 0; -} - -guint subscribe_dbus_signal_ctx(dbus_handle_h handle, sig_ctx *ctx, - const char *sender, const char *path, - const char *iface, const char *name, - GDBusSignalCallback _cb) -{ - dcl_dbus_handle(); - - if (!ctx) { - _E("wrong param ctx is null"); - return 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 0; - } - } - - if (!dh->conn) { - _E("connection is null. check bus status"); - return 0; - } - - if (!_cb) - _cb = _signal_reply_sync_cb; - - /* change context before subscribe */ - g_main_context_push_thread_default(ctx->context); - - ctx->sig_id = g_dbus_connection_signal_subscribe(dh->conn, - sender, iface, name, path, NULL, - G_DBUS_SIGNAL_FLAGS_NONE, _cb, - (void*)ctx, NULL); - - if (!ctx->sig_id) - _E("failed to subscribe signal"); - - return ctx->sig_id; -} - -int dbus_handle_signal_ctx_wait(sig_ctx *ctx) -{ - if (!ctx || !ctx->loop) - return -EINVAL; - - g_main_loop_run(ctx->loop); - - _D("quit g_main_loop"); - - return ctx->quit_reason; -} - -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; -} - -int dbus_handle_emit_dbus_signal(const char *dest, - 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, dest, path, iface, name, param, &err); - if (err) { - _E("%d %s\n", ret, err ? err->message : "NULL"); - g_error_free(err); - } - - return ret; -} - -int dbus_handle_emit_dbus_signal_sync(const char *dest, - 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, dest, path, iface, name, param, &err); - if (!ret) { - _E("%d %s\n", ret, err ? err->message : "NULL"); - g_error_free(err); - } - - ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err); - if (!ret) { - _E("%d %s\n", ret, err ? err->message : "NULL"); - g_error_free(err); - } - - return ret; -} - -int dbus_handle_flush_sync(dbus_handle_h handle) -{ - dcl_dbus_handle(); - GError *err = NULL; - gboolean 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 0; - } - } - - ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err); - if (!ret) { - _E("%d %s\n", ret, err ? err->message : "NULL"); - g_error_free(err); - } - - return ret; -} - -int dbus_handle_method_sync_with_reply_var(const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - GVariant **reply) -{ - GError *err = NULL; - GVariant *ret = NULL; - int err_val = 0; - 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 (param) - g_variant_unref(param); - return -EINVAL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - if (param) - g_variant_unref(param); - return -ECOMM; - } - - ret = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - param, 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); - if (g_error_matches(err, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) - err_val = -EPERM; - else - err_val = -ECOMM; - g_error_free(err); - return err_val; - } else { - _E("failed to g_dbus_connection_call_sync"); - } - return -ECOMM; - } - - if(reply) - *reply = ret; - else - g_variant_unref(ret); - - return err_val; -} - -int dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path, - const char *iface, const char *method, GVariant *param, GVariant **reply, int timeout) -{ - GError *err = NULL; - GVariant *ret; - 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 (param) - g_variant_unref(param); - return -EINVAL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - if (param) - g_variant_unref(param); - return -ECOMM; - } - - ret = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - param, 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 -ECOMM; - } - - if(reply) - *reply = ret; - else - g_variant_unref(ret); - - return 0; -} - -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; -} - -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); -} - -int 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, - GVariant **reply, - int *in_fdlist, - int in_size, - int **out_fdlist, - int *out_size) -{ - int err_val = 0; - GVariant *ret = NULL; - GError *err = NULL; - dbus_handle_s *dh = 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 -EINVAL; - } - if (in_fdlist && in_size == 0) { - _E("wrong in_fdlist is not null but in_size is 0"); - return -EINVAL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -EAGAIN; - } - - /* 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"); - err_val = -EAGAIN; - 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_connection_call_with_unix_fd_list_sync(dh->conn, - dest, path, iface, method, - param, NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - g_infdlist, &g_outfdlist, - NULL, &err); - if (!ret || err) { - if (err) { - _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message); - g_error_free(err); - } else { - _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:"); - if (param) - g_variant_unref(param); - if (g_infdlist) - g_object_unref(g_infdlist); - } - err_val = -EAGAIN; - goto out; - } - - if(reply) - *reply = ret; - else - g_variant_unref(ret); - - /* 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); - return err_val; -} - -int dbus_handle_method_sync_var(const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - int *output) -{ - int ret = 0; - 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 -EINVAL; - } - - ret = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param, &reply); - if (ret < 0) - return ret; - - if (!reply) - return -ECOMM; - - if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(i)", &result); - if(output) - *output = result; - } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(b)", &result_bool); - if(output) - *output = (int)result_bool; - } else { - ret = -ENOMSG; - } - - g_variant_unref(reply); - - return ret; -} - -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) - g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error during g_dbus_connection_call"); - - if (data && data->func) - data->func(NULL, data->data, err); - goto out; - } - - if (data && data->func) - data->func(reply, data->data, err); -out: - if (err) - g_error_free(err); - if (data) - free(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) -{ - 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_handle_method_async_pairs_with_reply(const char *dest, - const char *path, - const char *iface, - const char *method, - int num, - va_list args, - dbus_pending_cb cb, - int timeout_msec, - void *data) -{ - dbus_handle_s *dh = NULL; - pending_call_data *pdata = NULL; - GVariantBuilder *builder; - char *key, *value; - GVariant *param; - 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; - } - - // 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); - } - - param = g_variant_new("(a{ss})", builder); - g_variant_builder_unref(builder); - - 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 is null"); - 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 is null"); - 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 dbus_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); -} - -int check_systemd_active(void) -{ - int ret = FALSE; - GVariant *msg = NULL; - GVariant *var = NULL; - char *state; - - _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState"); - - ret = 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"), - &msg); - if (ret < 0) - return ret; - if (!msg) - return -EBADMSG; - - if (!g_variant_get_safe(msg, "(v)", &var)) { - _E("reply is not variant type"); - ret = -EBADMSG; - goto out; - } - if (!g_variant_get_safe(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; -} - -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; -} diff --git a/src/libgdbus/dbus-system.h b/src/libgdbus/dbus-system.h deleted file mode 100644 index c707d19..0000000 --- a/src/libgdbus/dbus-system.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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_SYSTEM_H__ -#define __DBUS_SYSTEM_H__ - -#include -#include -#include -#include -#include -#include - -#include "dbus-system-iface.h" - -typedef struct { - const unsigned char *data; - int size; -} dbus_byte; - - -typedef void *dbus_handle_h; - -typedef void *dbus_object_handle_h; - -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; - -typedef struct { - dbus_object_handle_h oh; - const char *name; - const dbus_method_s *methods; - int nr_methods; -} dbus_interface_u; - -typedef struct { - guint pid; - guint uid; - gchar *unique_name; - gchar *sec_label; -} GDBusCredentials; - -#define g_variant_get_safe(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) - -typedef void (*destroy_notified)(void *data); - -typedef void (*dbus_pending_cb)(GVariant *var, void *user_data, GError *err); - -typedef struct { - dbus_pending_cb func; - void *data; -} pending_call_data; - -dbus_handle_h dbus_handle_get_connection (GBusType bus_type, - gboolean priv); - -int dbus_handle_request_bus_name (dbus_handle_h handle, - const char *bus_name, - GBusNameAcquiredCallback acquired_handler, - GBusNameLostCallback lost_handler); - -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); - -int dbus_handle_method_sync_var (const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - int *output); - -int dbus_handle_method_async_var (const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param); - -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 dbus_handle_method_sync_with_reply_var (const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - GVariant **reply); - -int dbus_handle_method_sync_with_reply_var_timeout (const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - GVariant **reply, - 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_pairs_with_reply (const char *dest, - const char *path, - const char *iface, - const char *method, - int num, - va_list args, - dbus_pending_cb cb, - int timeout_msec, - void *data); - -gint* dbus_handle_get_unix_fd_list (GDBusMethodInvocation *invocation, - int *size); - -int 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, - GVariant **reply, - int *in_fdlist, - int in_size, - int **out_fdlist, - int *out_size); - - -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); - -int dbus_handle_emit_dbus_signal (const char *dest, - const char *path, - const char *iface, - const char *name, - GVariant *param); - -int dbus_handle_emit_dbus_signal_sync(const char *dest, - const char *path, - const char *iface, - const char *name, - GVariant *param); - -int dbus_handle_flush_sync(dbus_handle_h handle); - -enum ctx_quit_reason {CTX_QUIT_UNKNOWN, CTX_QUIT_NORMAL, CTX_QUIT_TIMEOUT}; - -typedef struct { - guint sig_id; - GMainContext *context; - GMainLoop *loop; - GSource *timeout_src; - GVariant *param; - enum ctx_quit_reason quit_reason; - void *user_data; -} sig_ctx; - -sig_ctx *dbus_handle_new_signal_ctx (void); - -void dbus_handle_free_signal_ctx (sig_ctx *ctx); - -guint subscribe_dbus_signal_ctx (dbus_handle_h handle, - sig_ctx *ctx, - const char *sender, - const char *path, - const char *iface, - const char *name, - GDBusSignalCallback cb); - -int dbus_handle_signal_ctx_wait (sig_ctx *ctx); - -int dbus_handle_signal_ctx_add_timeout (sig_ctx *ctx, - int timeout); - - - - -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); - -char** dbus_handle_get_owner_list (dbus_handle_h handle, - const char *bus_name); - -void dbus_handle_check_owner_name (dbus_handle_h handle, - const char *owner_name); - -int check_systemd_active (void); - -GVariant *dbus_handle_make_simple_array (const char *sig, - int *param); - - -#endif diff --git a/src/libgdbus/dbus-systemd.c b/src/libgdbus/dbus-systemd.c deleted file mode 100644 index 14c8a72..0000000 --- a/src/libgdbus/dbus-systemd.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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" - -#define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1" -#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" -#define SYSTEMD_DBUS_UNIT_PATH "/org/freedesktop/systemd1/unit/" - -#define SYSTEMD_DBUS_MANAGER_IFACE "org.freedesktop.systemd1.Manager" -#define SYSTEMD_DBUS_UNIT_IFACE "org.freedesktop.systemd1.Unit" -#define SYSTEMD_DBUS_SERVICE_IFACE "org.freedesktop.systemd1.Service" -#define SYSTEMD_DBUS_TARGET_IFACE "org.freedesktop.systemd1.Target" - -#define DBUS_IFACE_DBUS_PROPERTIES "org.freedesktop.DBus.Properties" - -#define SUFFIX_SERVICE ".service" -#define SUFFIX_SOCKET ".socket" -#define SUFFIX_BUSNAME ".busname" -#define SUFFIX_TARGET ".target" -#define SUFFIX_DEVICE ".device" -#define SUFFIX_MOUNT ".mount" -#define SUFFIX_SWAP ".swap" -#define SUFFIX_TIMER ".timer" -#define SUFFIX_PATH ".path" -#define SUFFIX_SLICE ".slice" -#define SUFFIX_SCOPE ".scope" - -#define UNIT_NAME_MAX 256 - -typedef struct { - const char *job_id; - const char *unit_name; -} unitinfo; - -static void _cb_JobRemoved(GDBusConnection *conn, - const char *sender, - const char *path, - const char *iface, - const char *name, - GVariant *param, - gpointer data) -{ - sig_ctx *ctx = data; - gchar *job_id = NULL; - gchar *unit_name = NULL; - unitinfo *uinfo = NULL; - - if (!ctx) { - _E("User data ctx is null"); - return ; - } - - uinfo = ctx->user_data; - if (!uinfo) { - _E("User_data uinfo is null"); - return ; - } - if (!g_variant_get_safe(param, "(uoss)", NULL, &job_id, &unit_name, NULL)) { - _E("Failed to get param"); - return ; - } - if (strcmp(uinfo->job_id, job_id) || strcmp(uinfo->unit_name, unit_name)) { - _E("Not matched: job_id:%s, unit_name:%s", job_id, unit_name); - goto err; - } - - /* otherwise, if matched signal, quit loop */ - - ctx->quit_reason = CTX_QUIT_NORMAL; - if (ctx->timeout_src) { - g_source_destroy(ctx->timeout_src); - ctx->timeout_src = NULL; - } - - g_main_loop_quit(ctx->loop); - -err: - g_free(job_id); - g_free(unit_name); -} - -static int _systemd_control_unit_wait(const char *method, - const char *name, - int timeout_msec) -{ - GVariant *reply = NULL; - gchar *objpath = NULL; - int ret = 0; - sig_ctx *ctx = NULL; - unitinfo uinfo; - int quit_reason; - - ctx = dbus_handle_new_signal_ctx(); - if (!ctx) - return -ENOMEM; - - _I("Starting: %s %s", method, name); - - /* synchronous signal subscription */ - ret = subscribe_dbus_signal_ctx(NULL, - ctx, - SYSTEMD_DBUS_SERVICE, - SYSTEMD_DBUS_PATH, - SYSTEMD_DBUS_IFACE_MANAGER, - "JobRemoved", - _cb_JobRemoved); - if (ret == 0) { - ret = -1; - goto finish; - } - - ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, - SYSTEMD_DBUS_PATH, - SYSTEMD_DBUS_MANAGER_IFACE, - method, - g_variant_new("(ss)", name, "replace"), - &reply); - if (ret < 0) - goto finish; - - if (!reply || !g_variant_get_safe(reply, "(o)", &objpath)) { - _E("fail (%s): no message", method); - ret = -EBADMSG; - goto finish; - } - - uinfo.job_id = objpath; - uinfo.unit_name = name; - ctx->user_data = &uinfo; - - /* set timeout */ - ret = dbus_handle_signal_ctx_add_timeout(ctx, timeout_msec); - if (ret < 0) { - _E("Failed to set timeout, %d", ret); - goto finish; - } - - /* run loop and wait signal callback */ - quit_reason = dbus_handle_signal_ctx_wait(ctx); - if (quit_reason != CTX_QUIT_NORMAL) { - ret = -1; - _E("Failed to receive JobRemoved signal %d", quit_reason); - goto finish; - } - - _I("Finished: %s %s", method, name); - -finish: - if (reply) - g_variant_unref(reply); - g_free(objpath); - - dbus_handle_free_signal_ctx(ctx); - - return ret; -} - -static int _systemd_control_unit_async(const char *method, const char *name) -{ - GVariant *reply = NULL; - gchar *objpath = NULL; - int ret = 0; - - _I("Starting: %s %s", method, name); - - ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, - SYSTEMD_DBUS_PATH, - SYSTEMD_DBUS_MANAGER_IFACE, - method, - g_variant_new("(ss)", name, "replace"), - &reply); - if (ret < 0) - goto finish; - - if (!reply || !g_variant_get_safe(reply, "(o)", &objpath)) { - _E("fail (%s): no message", method); - ret = -EBADMSG; - goto finish; - } - - _I("Finished: %s %s", method, name); -finish: - if (reply) - g_variant_unref(reply); - g_free(objpath); - - return ret; -} - -static int _change_suffix(const char *name, - const char *suffix, - char **new_name) -{ - char *buf = NULL; - char *ext = NULL; - unsigned int len = 0; - int ret = 0; - - if (!name || !suffix || !new_name) { - _E("Wrong param name:%s, suffix:%s, new_name:%s (null)", - name ? : "(null)", suffix ? : "(null)", new_name ? "not" : ""); - return -EINVAL; - } - - ext = strrchr(name, '.'); - if (ext == name) { - _E("Wrong file name %s", name); - return -EINVAL; - } - - /* if ext is same as suffix */ - if (ext && strcmp(ext, suffix) == 0) { - *new_name = strdup(name); - return 0; - } - - /* otherwise, make new unit name */ - if (ext) - len = ext - name; - else - len = strlen(name); - - /* check max len */ - if ((len + strlen(suffix)) >= UNIT_NAME_MAX) { - _E("Name is too long:%d", (len + strlen(suffix))); - return -ENAMETOOLONG; - } - - buf = (char *)malloc(sizeof(char) * (len + strlen(suffix) + 1)); - if (!buf) { - _E("Failed to alloc mem"); - return -ENOMEM; - } - - ret = snprintf(buf, len + 1, "%s", name); - if (ret < 0) { - ret = -errno; - _E("Failed to snprintf %d", ret); - goto err; - } - ret = snprintf(buf + len, strlen(suffix) + 1, "%s", suffix); - if (ret < 0) { - ret = -errno; - _E("Failed to snprintf %d", ret); - goto err; - } - - *new_name = buf; - - return 0; - -err: - free(buf); - return ret; -} - -/* -_systemd_control_unit - -Start or Stop systemd unit. - 1) Wait for started/stopped - - Send StartUnit/StopUnit Method call(sync) - reply:(o):/org/freedesktop/systemd1/job/[jobid] - - Wait JobRemoved signal from systemd - (uoss):(uint32 [jobid], objectpath '/org/freedesktop/systemd1/job/[jobid]', '[unit name]', '[result]') - 2) Asynchronous - - Send StartUnit/StopUnit Method call(sync) - -@param name: unit name -@param suffix: (nullable): change extension of unit name, or %NULL -@param timeout_msec: the timeout in milliseconds, -1 to use the default -@param method: method name, "StartUnit" or "StopUnit" -@param wait: %TRUE -Returns: the exit status -*/ -static int _systemd_control_unit(const char *name, - const char *suffix, - int timeout_msec, - const char *method, - int wait) -{ - char *new_name = NULL; - int ret = 0; - - if (!name || !method) { - _E("Wrong param name %s, method %s", name ? : "(null)", method ? : "(null)"); - return -EINVAL; - } - if (timeout_msec < -1) { - _E("wrong timeout. timeout(>=0 or -1)"); - return -EINVAL; - } - - if (suffix) { - ret = _change_suffix(name, suffix, &new_name); - if (ret < 0) - return ret; - name = new_name; - } else { - if (strlen(name) > UNIT_NAME_MAX) { - _E("Invalid name length %d(>%d)", strlen(name), UNIT_NAME_MAX); - return -EINVAL; - } - } - - if (wait) - ret = _systemd_control_unit_wait(method, name, timeout_msec); - else - ret = _systemd_control_unit_async(method, name); - - if (new_name) - free(new_name); - - return ret; -} - -int systemd_start_unit_wait_started(const char *name, const char *suffix, int timeout_msec) -{ - return _systemd_control_unit(name, suffix, timeout_msec, "StartUnit", TRUE); -} - -int systemd_stop_unit_wait_stopped(const char *name, const char *suffix, int timeout_msec) -{ - return _systemd_control_unit(name, suffix, timeout_msec, "StopUnit", TRUE); -} - -int systemd_start_unit_async(const char *name, const char *suffix) -{ - return _systemd_control_unit(name, suffix, -1, "StartUnit", FALSE); -} - -int systemd_stop_unit_async(const char *name, const char *suffix) -{ - return _systemd_control_unit(name, suffix, -1, "StopUnit", FALSE); -} - -#define SYSTEMD_UNIT_ESCAPE_CHAR ".-" - -static char *systemd_get_unit_dbus_path(const char *unit) -{ - char *path = NULL; - int i; - size_t p, k, prefix_len, unit_len; - size_t path_len, len, escape; - - if (!unit) - return NULL; - unit_len = strlen(unit); - - for (escape = 0, p = 0; p < unit_len; escape++) { - k = strcspn(unit + p, SYSTEMD_UNIT_ESCAPE_CHAR); - if (p + k >= unit_len) - break; - p += k+1; - } - - prefix_len = strlen(SYSTEMD_DBUS_UNIT_PATH); - /* assume we try to get object path of foo-bar.service then - * the object path will be - * "/org/freedesktop/systemd1/unit/foo_2dbar_2eservice\n". In - * this case we can find two escape characters, one of escape - * char('-') is changed to three of char("_2d"). So the total - * length will be: */ - /* (PREFIX) + (unit - escape + 3*escape) + NULL */ - path_len = prefix_len + (unit_len - escape) - + (escape * 3 * sizeof(char)) + 1; - path = (char *)calloc(path_len, sizeof(char)); - if (!path) - return NULL; - - strncpy(path, SYSTEMD_DBUS_UNIT_PATH, prefix_len + 1); - for (i = 0, p = 0; i <= escape; i++) { - k = strcspn(unit + p, SYSTEMD_UNIT_ESCAPE_CHAR); - strncpy(path + prefix_len, unit + p, k); - if (k < strlen(unit + p)) { - len = path_len - (prefix_len + k); - snprintf(path + prefix_len + k, len, - "_%x", *(unit + p + k) & 0xff); - prefix_len += k + 3; - p += k+1; - } - } - - return path; -} - -GVariant *systemd_get_manager_property(const char *property) -{ - GVariant *reply = NULL; - GVariant *val = NULL; - int ret = 0; - - if (!property) - return NULL; - - ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, - SYSTEMD_DBUS_PATH, - DBUS_IFACE_DBUS_PROPERTIES, - "Get", - g_variant_new("(ss)", SYSTEMD_DBUS_MANAGER_IFACE, property), - &reply); - if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) - _E("Failed to get variant"); - if (reply) - g_variant_unref(reply); - - return val; -} - -GVariant *systemd_get_unit_property(const char *unit, const char *property) -{ - char *escaped; - GVariant *reply = NULL; - GVariant *val = NULL; - int ret = 0; - - if (!unit || !property) - return NULL; - - escaped = systemd_get_unit_dbus_path(unit); - - ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, - escaped, - DBUS_IFACE_DBUS_PROPERTIES, - "Get", - g_variant_new("(ss)", SYSTEMD_DBUS_UNIT_IFACE, property), - &reply); - - if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) - _E("Failed to get variant"); - if (reply) - g_variant_unref(reply); - free(escaped); - - return val; -} - -GVariant *systemd_get_service_property(const char *unit, const char *property) -{ - char *escaped; - GVariant *reply = NULL; - GVariant *val = NULL; - int ret = 0; - - if (!unit || !property) - return NULL; - - escaped = systemd_get_unit_dbus_path(unit); - - ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, - escaped, - DBUS_IFACE_DBUS_PROPERTIES, - "Get", - g_variant_new("(ss)", SYSTEMD_DBUS_SERVICE_IFACE, property), - &reply); - if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) - _E("Failed to get variant"); - if (reply) - g_variant_unref(reply); - free(escaped); - return val; -} diff --git a/src/libgdbus/dbus-systemd.h b/src/libgdbus/dbus-systemd.h deleted file mode 100644 index 4d15200..0000000 --- a/src/libgdbus/dbus-systemd.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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_SYSTEMD_H__ -#define __DBUS_SYSTEMD_H__ - -#include "dbus-system.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int systemd_start_unit_wait_started (const char *name, - const char *suffix, - int timeout_msec); - -int systemd_stop_unit_wait_stopped (const char *name, - const char *suffix, - int timeout_msec); - -int systemd_start_unit_async (const char *name, - const char *suffix); - -int systemd_stop_unit_async (const char *name, - const char *suffix); - -GVariant *systemd_get_manager_property (const char *property); - - -GVariant *systemd_get_unit_property (const char *unit, - const char *property); - -GVariant *systemd_get_service_property (const char *unit, - const char *property); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __DBUS_SYSTEMD_H__ */ - diff --git a/src/libgdbus/libgdbus.c b/src/libgdbus/libgdbus.c new file mode 100644 index 0000000..499a449 --- /dev/null +++ b/src/libgdbus/libgdbus.c @@ -0,0 +1,2639 @@ +/* + * libsyscommon + * + * Copyright (c) 2019 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 "libgdbus.h" + +/* 10 seconds */ +#define DBUS_REPLY_TIMEOUT (10000) + +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); + +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); + if (!dh->conn) { + dbus_handle_unlock(dh); + return NULL; + } + dh->priv = FALSE; + dh->bus_type = bus_type; + } + + 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; + 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; + } + + 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; +} + +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 is null"); + 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; +} + +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); +} + +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); +} + +static void _signal_reply_sync_cb(GDBusConnection *conn, + const gchar *sender, + const gchar *path, + const gchar *iface, + const gchar *name, + GVariant *param, + gpointer data) +{ + sig_ctx *ctx = data; + if (!ctx) { + _E("user data is null"); + assert(0); + } + + ctx->param = g_variant_ref(param); + ctx->quit_reason = CTX_QUIT_NORMAL; + + if (ctx->timeout_src) { + g_source_destroy(ctx->timeout_src); + ctx->timeout_src = NULL; + } + g_main_loop_quit(ctx->loop); +} + +sig_ctx *dbus_handle_new_signal_ctx(void) +{ + sig_ctx *ctx; + + ctx = (sig_ctx *)malloc(sizeof(sig_ctx)); + if (!ctx) { + _E("failed to alloc mem"); + return NULL; + } + + ctx->sig_id = 0; + + ctx->context = g_main_context_new(); + if (!ctx->context) { + _E("failed to alloc context"); + free(ctx); + return NULL; + } + ctx->loop = g_main_loop_new(ctx->context, FALSE); + if (!ctx->loop) { + _E("failed to alloc main loop"); + g_main_context_unref(ctx->context); + free(ctx); + return NULL; + } + ctx->timeout_src = NULL; + ctx->param = NULL; + ctx->quit_reason = CTX_QUIT_UNKNOWN; + ctx->user_data = NULL; + + return ctx; +} + +void dbus_handle_free_signal_ctx(sig_ctx *ctx) +{ + if (!ctx) + return ; + + if (ctx->param) { + g_variant_unref(ctx->param); + ctx->param = NULL; + } + if (ctx->sig_id) { + unsubscribe_dbus_signal(NULL, ctx->sig_id); + ctx->sig_id = 0; + } + if (ctx->timeout_src) { + g_source_destroy(ctx->timeout_src); + ctx->timeout_src = NULL; + } + if (ctx->context) { + g_main_context_pop_thread_default(ctx->context); + g_main_context_unref(ctx->context); + ctx->context = NULL; + } + if (ctx->loop) { + g_main_loop_unref(ctx->loop); + ctx->loop = NULL; + } + free(ctx); +} + +static gboolean _cb_ctx_timeout(gpointer user_data) +{ + sig_ctx *ctx = user_data; + + if (!ctx) { + _E("user_data is null"); + return FALSE; + } + + ctx->quit_reason = CTX_QUIT_TIMEOUT; + /* if cb return FALSE, source will be destroyed */ + ctx->timeout_src = NULL; + + unsubscribe_dbus_signal(NULL, ctx->sig_id); + ctx->sig_id = 0; + + g_main_loop_quit(ctx->loop); + + return FALSE; +} + +#define CTX_MAX_TIMEOUT 25000 + +int dbus_handle_signal_ctx_add_timeout(sig_ctx *ctx, int timeout_msec) +{ + GSource *src = NULL; + + if (!ctx) + return -EINVAL; + if (timeout_msec < -1) + return -EINVAL; + + if (timeout_msec == -1 || timeout_msec >= CTX_MAX_TIMEOUT) + timeout_msec = CTX_MAX_TIMEOUT; + + src = g_timeout_source_new(timeout_msec); + if (!src) + return -ENOMEM; + + g_source_set_callback(src, _cb_ctx_timeout, ctx, NULL); + g_source_attach(src, ctx->context); + g_source_unref(src); + + ctx->timeout_src = src; + + return 0; +} + +guint subscribe_dbus_signal_ctx(dbus_handle_h handle, sig_ctx *ctx, + const char *sender, const char *path, + const char *iface, const char *name, + GDBusSignalCallback _cb) +{ + dcl_dbus_handle(); + + if (!ctx) { + _E("wrong param ctx is null"); + return 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 0; + } + } + + if (!dh->conn) { + _E("connection is null. check bus status"); + return 0; + } + + if (!_cb) + _cb = _signal_reply_sync_cb; + + /* change context before subscribe */ + g_main_context_push_thread_default(ctx->context); + + ctx->sig_id = g_dbus_connection_signal_subscribe(dh->conn, + sender, iface, name, path, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, _cb, + (void*)ctx, NULL); + + if (!ctx->sig_id) + _E("failed to subscribe signal"); + + return ctx->sig_id; +} + +int dbus_handle_signal_ctx_wait(sig_ctx *ctx) +{ + if (!ctx || !ctx->loop) + return -EINVAL; + + g_main_loop_run(ctx->loop); + + _D("quit g_main_loop"); + + return ctx->quit_reason; +} + +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; +} + +int dbus_handle_emit_dbus_signal(const char *dest, + 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, dest, path, iface, name, param, &err); + if (err) { + _E("%d %s\n", ret, err ? err->message : "NULL"); + g_error_free(err); + } + + return ret; +} + +int dbus_handle_emit_dbus_signal_sync(const char *dest, + 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, dest, path, iface, name, param, &err); + if (!ret) { + _E("%d %s\n", ret, err ? err->message : "NULL"); + g_error_free(err); + } + + ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err); + if (!ret) { + _E("%d %s\n", ret, err ? err->message : "NULL"); + g_error_free(err); + } + + return ret; +} + +int dbus_handle_flush_sync(dbus_handle_h handle) +{ + dcl_dbus_handle(); + GError *err = NULL; + gboolean 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 0; + } + } + + ret = g_dbus_connection_flush_sync(dh->conn, NULL, &err); + if (!ret) { + _E("%d %s\n", ret, err ? err->message : "NULL"); + g_error_free(err); + } + + return ret; +} + +int dbus_handle_method_sync_with_reply_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + GVariant **reply) +{ + GError *err = NULL; + GVariant *ret = NULL; + int err_val = 0; + 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 (param) + g_variant_unref(param); + return -EINVAL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + if (param) + g_variant_unref(param); + return -ECOMM; + } + + ret = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + param, 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); + if (g_error_matches(err, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) + err_val = -EPERM; + else + err_val = -ECOMM; + g_error_free(err); + return err_val; + } else { + _E("failed to g_dbus_connection_call_sync"); + } + return -ECOMM; + } + + if(reply) + *reply = ret; + else + g_variant_unref(ret); + + return err_val; +} + +int dbus_handle_method_sync_with_reply_var_timeout(const char *dest, const char *path, + const char *iface, const char *method, GVariant *param, GVariant **reply, int timeout) +{ + GError *err = NULL; + GVariant *ret; + 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 (param) + g_variant_unref(param); + return -EINVAL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + if (param) + g_variant_unref(param); + return -ECOMM; + } + + ret = g_dbus_connection_call_sync(dh->conn, + dest, path, iface, method, + param, 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 -ECOMM; + } + + if(reply) + *reply = ret; + else + g_variant_unref(ret); + + return 0; +} + +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; +} + +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); +} + +int 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, + GVariant **reply, + int *in_fdlist, + int in_size, + int **out_fdlist, + int *out_size) +{ + int err_val = 0; + GVariant *ret = NULL; + GError *err = NULL; + dbus_handle_s *dh = 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 -EINVAL; + } + if (in_fdlist && in_size == 0) { + _E("wrong in_fdlist is not null but in_size is 0"); + return -EINVAL; + } + + dh = _dbus_handle_get_default_connection(); + if (!dh) { + _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); + return -EAGAIN; + } + + /* 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"); + err_val = -EAGAIN; + 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_connection_call_with_unix_fd_list_sync(dh->conn, + dest, path, iface, method, + param, NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + g_infdlist, &g_outfdlist, + NULL, &err); + if (!ret || err) { + if (err) { + _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:%s", err->message); + g_error_free(err); + } else { + _E("failed to g_dbus_connection_call_with_unix_fd_list_sync:"); + if (param) + g_variant_unref(param); + if (g_infdlist) + g_object_unref(g_infdlist); + } + err_val = -EAGAIN; + goto out; + } + + if(reply) + *reply = ret; + else + g_variant_unref(ret); + + /* 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); + return err_val; +} + +int dbus_handle_method_sync_var(const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + int *output) +{ + int ret = 0; + 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 -EINVAL; + } + + ret = dbus_handle_method_sync_with_reply_var(dest, path, iface, method, param, &reply); + if (ret < 0) + return ret; + + if (!reply) + return -ECOMM; + + if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(i)", &result); + if(output) + *output = result; + } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { + g_variant_get(reply, "(b)", &result_bool); + if(output) + *output = (int)result_bool; + } else { + ret = -ENOMSG; + } + + g_variant_unref(reply); + + return ret; +} + +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) + g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error during g_dbus_connection_call"); + + if (data && data->func) + data->func(NULL, data->data, err); + goto out; + } + + if (data && data->func) + data->func(reply, data->data, err); +out: + if (err) + g_error_free(err); + if (data) + free(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) +{ + 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_handle_method_async_pairs_with_reply(const char *dest, + const char *path, + const char *iface, + const char *method, + int num, + va_list args, + dbus_pending_cb cb, + int timeout_msec, + void *data) +{ + dbus_handle_s *dh = NULL; + pending_call_data *pdata = NULL; + GVariantBuilder *builder; + char *key, *value; + GVariant *param; + 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; + } + + // 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); + } + + param = g_variant_new("(a{ss})", builder); + g_variant_builder_unref(builder); + + 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 is null"); + 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 is null"); + 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 dbus_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); +} + +int check_systemd_active(void) +{ + int ret = FALSE; + GVariant *msg = NULL; + GVariant *var = NULL; + char *state; + + _I("%s %s", "org.freedesktop.systemd1.Unit", "ActiveState"); + + ret = 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"), + &msg); + if (ret < 0) + return ret; + if (!msg) + return -EBADMSG; + + if (!g_variant_get_safe(msg, "(v)", &var)) { + _E("reply is not variant type"); + ret = -EBADMSG; + goto out; + } + if (!g_variant_get_safe(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; +} + +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; +} diff --git a/src/libgdbus/libgdbus.h b/src/libgdbus/libgdbus.h new file mode 100644 index 0000000..99fdc3e --- /dev/null +++ b/src/libgdbus/libgdbus.h @@ -0,0 +1,266 @@ +/* + * libsyscommon + * + * Copyright (c) 2019 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_SYSTEM_H__ +#define __DBUS_SYSTEM_H__ + +#include +#include +#include +#include +#include +#include + +#include "dbus-iface-system.h" + +typedef struct { + const unsigned char *data; + int size; +} dbus_byte; + + +typedef void *dbus_handle_h; + +typedef void *dbus_object_handle_h; + +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; + +typedef struct { + dbus_object_handle_h oh; + const char *name; + const dbus_method_s *methods; + int nr_methods; +} dbus_interface_u; + +typedef struct { + guint pid; + guint uid; + gchar *unique_name; + gchar *sec_label; +} GDBusCredentials; + +#define g_variant_get_safe(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) + +typedef void (*destroy_notified)(void *data); + +typedef void (*dbus_pending_cb)(GVariant *var, void *user_data, GError *err); + +typedef struct { + dbus_pending_cb func; + void *data; +} pending_call_data; + +dbus_handle_h dbus_handle_get_connection (GBusType bus_type, + gboolean priv); + +int dbus_handle_request_bus_name (dbus_handle_h handle, + const char *bus_name, + GBusNameAcquiredCallback acquired_handler, + GBusNameLostCallback lost_handler); + +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); + +int dbus_handle_method_sync_var (const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + int *output); + +int dbus_handle_method_async_var (const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param); + +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 dbus_handle_method_sync_with_reply_var (const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + GVariant **reply); + +int dbus_handle_method_sync_with_reply_var_timeout (const char *dest, + const char *path, + const char *iface, + const char *method, + GVariant *param, + GVariant **reply, + 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_pairs_with_reply (const char *dest, + const char *path, + const char *iface, + const char *method, + int num, + va_list args, + dbus_pending_cb cb, + int timeout_msec, + void *data); + +gint* dbus_handle_get_unix_fd_list (GDBusMethodInvocation *invocation, + int *size); + +int 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, + GVariant **reply, + int *in_fdlist, + int in_size, + int **out_fdlist, + int *out_size); + + +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); + +int dbus_handle_emit_dbus_signal (const char *dest, + const char *path, + const char *iface, + const char *name, + GVariant *param); + +int dbus_handle_emit_dbus_signal_sync(const char *dest, + const char *path, + const char *iface, + const char *name, + GVariant *param); + +int dbus_handle_flush_sync(dbus_handle_h handle); + +enum ctx_quit_reason {CTX_QUIT_UNKNOWN, CTX_QUIT_NORMAL, CTX_QUIT_TIMEOUT}; + +typedef struct { + guint sig_id; + GMainContext *context; + GMainLoop *loop; + GSource *timeout_src; + GVariant *param; + enum ctx_quit_reason quit_reason; + void *user_data; +} sig_ctx; + +sig_ctx *dbus_handle_new_signal_ctx (void); + +void dbus_handle_free_signal_ctx (sig_ctx *ctx); + +guint subscribe_dbus_signal_ctx (dbus_handle_h handle, + sig_ctx *ctx, + const char *sender, + const char *path, + const char *iface, + const char *name, + GDBusSignalCallback cb); + +int dbus_handle_signal_ctx_wait (sig_ctx *ctx); + +int dbus_handle_signal_ctx_add_timeout (sig_ctx *ctx, + int timeout); + + + + +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); + +char** dbus_handle_get_owner_list (dbus_handle_h handle, + const char *bus_name); + +void dbus_handle_check_owner_name (dbus_handle_h handle, + const char *owner_name); + +int check_systemd_active (void); + +GVariant *dbus_handle_make_simple_array (const char *sig, + int *param); + + +#endif diff --git a/src/libsystemd/libsystemd.c b/src/libsystemd/libsystemd.c new file mode 100644 index 0000000..a463118 --- /dev/null +++ b/src/libsystemd/libsystemd.c @@ -0,0 +1,523 @@ +/* + * libsyscommon + * + * Copyright (c) 2019 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" + +#define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1" +#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" +#define SYSTEMD_DBUS_UNIT_PATH "/org/freedesktop/systemd1/unit/" + +#define SYSTEMD_DBUS_MANAGER_IFACE "org.freedesktop.systemd1.Manager" +#define SYSTEMD_DBUS_UNIT_IFACE "org.freedesktop.systemd1.Unit" +#define SYSTEMD_DBUS_SERVICE_IFACE "org.freedesktop.systemd1.Service" +#define SYSTEMD_DBUS_TARGET_IFACE "org.freedesktop.systemd1.Target" + +#define DBUS_IFACE_DBUS_PROPERTIES "org.freedesktop.DBus.Properties" + +#define SUFFIX_SERVICE ".service" +#define SUFFIX_SOCKET ".socket" +#define SUFFIX_BUSNAME ".busname" +#define SUFFIX_TARGET ".target" +#define SUFFIX_DEVICE ".device" +#define SUFFIX_MOUNT ".mount" +#define SUFFIX_SWAP ".swap" +#define SUFFIX_TIMER ".timer" +#define SUFFIX_PATH ".path" +#define SUFFIX_SLICE ".slice" +#define SUFFIX_SCOPE ".scope" + +#define UNIT_NAME_MAX 256 + +typedef struct { + const char *job_id; + const char *unit_name; +} unitinfo; + +static void _cb_JobRemoved(GDBusConnection *conn, + const char *sender, + const char *path, + const char *iface, + const char *name, + GVariant *param, + gpointer data) +{ + sig_ctx *ctx = data; + gchar *job_id = NULL; + gchar *unit_name = NULL; + unitinfo *uinfo = NULL; + + if (!ctx) { + _E("User data ctx is null"); + return ; + } + + uinfo = ctx->user_data; + if (!uinfo) { + _E("User_data uinfo is null"); + return ; + } + if (!g_variant_get_safe(param, "(uoss)", NULL, &job_id, &unit_name, NULL)) { + _E("Failed to get param"); + return ; + } + if (strcmp(uinfo->job_id, job_id) || strcmp(uinfo->unit_name, unit_name)) { + _E("Not matched: job_id:%s, unit_name:%s", job_id, unit_name); + goto err; + } + + /* otherwise, if matched signal, quit loop */ + + ctx->quit_reason = CTX_QUIT_NORMAL; + if (ctx->timeout_src) { + g_source_destroy(ctx->timeout_src); + ctx->timeout_src = NULL; + } + + g_main_loop_quit(ctx->loop); + +err: + g_free(job_id); + g_free(unit_name); +} + +static int _systemd_control_unit_wait(const char *method, + const char *name, + int timeout_msec) +{ + GVariant *reply = NULL; + gchar *objpath = NULL; + int ret = 0; + sig_ctx *ctx = NULL; + unitinfo uinfo; + int quit_reason; + + ctx = dbus_handle_new_signal_ctx(); + if (!ctx) + return -ENOMEM; + + _I("Starting: %s %s", method, name); + + /* synchronous signal subscription */ + ret = subscribe_dbus_signal_ctx(NULL, + ctx, + SYSTEMD_DBUS_SERVICE, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_IFACE_MANAGER, + "JobRemoved", + _cb_JobRemoved); + if (ret == 0) { + ret = -1; + goto finish; + } + + ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_MANAGER_IFACE, + method, + g_variant_new("(ss)", name, "replace"), + &reply); + if (ret < 0) + goto finish; + + if (!reply || !g_variant_get_safe(reply, "(o)", &objpath)) { + _E("fail (%s): no message", method); + ret = -EBADMSG; + goto finish; + } + + uinfo.job_id = objpath; + uinfo.unit_name = name; + ctx->user_data = &uinfo; + + /* set timeout */ + ret = dbus_handle_signal_ctx_add_timeout(ctx, timeout_msec); + if (ret < 0) { + _E("Failed to set timeout, %d", ret); + goto finish; + } + + /* run loop and wait signal callback */ + quit_reason = dbus_handle_signal_ctx_wait(ctx); + if (quit_reason != CTX_QUIT_NORMAL) { + ret = -1; + _E("Failed to receive JobRemoved signal %d", quit_reason); + goto finish; + } + + _I("Finished: %s %s", method, name); + +finish: + if (reply) + g_variant_unref(reply); + g_free(objpath); + + dbus_handle_free_signal_ctx(ctx); + + return ret; +} + +static int _systemd_control_unit_async(const char *method, const char *name) +{ + GVariant *reply = NULL; + gchar *objpath = NULL; + int ret = 0; + + _I("Starting: %s %s", method, name); + + ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_MANAGER_IFACE, + method, + g_variant_new("(ss)", name, "replace"), + &reply); + if (ret < 0) + goto finish; + + if (!reply || !g_variant_get_safe(reply, "(o)", &objpath)) { + _E("fail (%s): no message", method); + ret = -EBADMSG; + goto finish; + } + + _I("Finished: %s %s", method, name); +finish: + if (reply) + g_variant_unref(reply); + g_free(objpath); + + return ret; +} + +static int _change_suffix(const char *name, + const char *suffix, + char **new_name) +{ + char *buf = NULL; + char *ext = NULL; + unsigned int len = 0; + int ret = 0; + + if (!name || !suffix || !new_name) { + _E("Wrong param name:%s, suffix:%s, new_name:%s (null)", + name ? : "(null)", suffix ? : "(null)", new_name ? "not" : ""); + return -EINVAL; + } + + ext = strrchr(name, '.'); + if (ext == name) { + _E("Wrong file name %s", name); + return -EINVAL; + } + + /* if ext is same as suffix */ + if (ext && strcmp(ext, suffix) == 0) { + *new_name = strdup(name); + return 0; + } + + /* otherwise, make new unit name */ + if (ext) + len = ext - name; + else + len = strlen(name); + + /* check max len */ + if ((len + strlen(suffix)) >= UNIT_NAME_MAX) { + _E("Name is too long:%d", (len + strlen(suffix))); + return -ENAMETOOLONG; + } + + buf = (char *)malloc(sizeof(char) * (len + strlen(suffix) + 1)); + if (!buf) { + _E("Failed to alloc mem"); + return -ENOMEM; + } + + ret = snprintf(buf, len + 1, "%s", name); + if (ret < 0) { + ret = -errno; + _E("Failed to snprintf %d", ret); + goto err; + } + ret = snprintf(buf + len, strlen(suffix) + 1, "%s", suffix); + if (ret < 0) { + ret = -errno; + _E("Failed to snprintf %d", ret); + goto err; + } + + *new_name = buf; + + return 0; + +err: + free(buf); + return ret; +} + +/* +_systemd_control_unit + +Start or Stop systemd unit. + 1) Wait for started/stopped + - Send StartUnit/StopUnit Method call(sync) + reply:(o):/org/freedesktop/systemd1/job/[jobid] + - Wait JobRemoved signal from systemd + (uoss):(uint32 [jobid], objectpath '/org/freedesktop/systemd1/job/[jobid]', '[unit name]', '[result]') + 2) Asynchronous + - Send StartUnit/StopUnit Method call(sync) + +@param name: unit name +@param suffix: (nullable): change extension of unit name, or %NULL +@param timeout_msec: the timeout in milliseconds, -1 to use the default +@param method: method name, "StartUnit" or "StopUnit" +@param wait: %TRUE +Returns: the exit status +*/ +static int _systemd_control_unit(const char *name, + const char *suffix, + int timeout_msec, + const char *method, + int wait) +{ + char *new_name = NULL; + int ret = 0; + + if (!name || !method) { + _E("Wrong param name %s, method %s", name ? : "(null)", method ? : "(null)"); + return -EINVAL; + } + if (timeout_msec < -1) { + _E("wrong timeout. timeout(>=0 or -1)"); + return -EINVAL; + } + + if (suffix) { + ret = _change_suffix(name, suffix, &new_name); + if (ret < 0) + return ret; + name = new_name; + } else { + if (strlen(name) > UNIT_NAME_MAX) { + _E("Invalid name length %d(>%d)", strlen(name), UNIT_NAME_MAX); + return -EINVAL; + } + } + + if (wait) + ret = _systemd_control_unit_wait(method, name, timeout_msec); + else + ret = _systemd_control_unit_async(method, name); + + if (new_name) + free(new_name); + + return ret; +} + +int systemd_start_unit_wait_started(const char *name, const char *suffix, int timeout_msec) +{ + return _systemd_control_unit(name, suffix, timeout_msec, "StartUnit", TRUE); +} + +int systemd_stop_unit_wait_stopped(const char *name, const char *suffix, int timeout_msec) +{ + return _systemd_control_unit(name, suffix, timeout_msec, "StopUnit", TRUE); +} + +int systemd_start_unit_async(const char *name, const char *suffix) +{ + return _systemd_control_unit(name, suffix, -1, "StartUnit", FALSE); +} + +int systemd_stop_unit_async(const char *name, const char *suffix) +{ + return _systemd_control_unit(name, suffix, -1, "StopUnit", FALSE); +} + +#define SYSTEMD_UNIT_ESCAPE_CHAR ".-" + +static char *systemd_get_unit_dbus_path(const char *unit) +{ + char *path = NULL; + int i; + size_t p, k, prefix_len, unit_len; + size_t path_len, len, escape; + + if (!unit) + return NULL; + unit_len = strlen(unit); + + for (escape = 0, p = 0; p < unit_len; escape++) { + k = strcspn(unit + p, SYSTEMD_UNIT_ESCAPE_CHAR); + if (p + k >= unit_len) + break; + p += k+1; + } + + prefix_len = strlen(SYSTEMD_DBUS_UNIT_PATH); + /* assume we try to get object path of foo-bar.service then + * the object path will be + * "/org/freedesktop/systemd1/unit/foo_2dbar_2eservice\n". In + * this case we can find two escape characters, one of escape + * char('-') is changed to three of char("_2d"). So the total + * length will be: */ + /* (PREFIX) + (unit - escape + 3*escape) + NULL */ + path_len = prefix_len + (unit_len - escape) + + (escape * 3 * sizeof(char)) + 1; + path = (char *)calloc(path_len, sizeof(char)); + if (!path) + return NULL; + + strncpy(path, SYSTEMD_DBUS_UNIT_PATH, prefix_len + 1); + for (i = 0, p = 0; i <= escape; i++) { + k = strcspn(unit + p, SYSTEMD_UNIT_ESCAPE_CHAR); + strncpy(path + prefix_len, unit + p, k); + if (k < strlen(unit + p)) { + len = path_len - (prefix_len + k); + snprintf(path + prefix_len + k, len, + "_%x", *(unit + p + k) & 0xff); + prefix_len += k + 3; + p += k+1; + } + } + + return path; +} + +GVariant *systemd_get_manager_property(const char *property) +{ + GVariant *reply = NULL; + GVariant *val = NULL; + int ret = 0; + + if (!property) + return NULL; + + ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, + SYSTEMD_DBUS_PATH, + DBUS_IFACE_DBUS_PROPERTIES, + "Get", + g_variant_new("(ss)", SYSTEMD_DBUS_MANAGER_IFACE, property), + &reply); + if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) + _E("Failed to get variant"); + if (reply) + g_variant_unref(reply); + + return val; +} + +GVariant *systemd_get_unit_property(const char *unit, const char *property) +{ + char *escaped; + GVariant *reply = NULL; + GVariant *val = NULL; + int ret = 0; + + if (!unit || !property) + return NULL; + + escaped = systemd_get_unit_dbus_path(unit); + + ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, + escaped, + DBUS_IFACE_DBUS_PROPERTIES, + "Get", + g_variant_new("(ss)", SYSTEMD_DBUS_UNIT_IFACE, property), + &reply); + + if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) + _E("Failed to get variant"); + if (reply) + g_variant_unref(reply); + free(escaped); + + return val; +} + +GVariant *systemd_get_service_property(const char *unit, const char *property) +{ + char *escaped; + GVariant *reply = NULL; + GVariant *val = NULL; + int ret = 0; + + if (!unit || !property) + return NULL; + + escaped = systemd_get_unit_dbus_path(unit); + + ret = dbus_handle_method_sync_with_reply_var(SYSTEMD_DBUS_DEST, + escaped, + DBUS_IFACE_DBUS_PROPERTIES, + "Get", + g_variant_new("(ss)", SYSTEMD_DBUS_SERVICE_IFACE, property), + &reply); + if (!reply || !g_variant_get_safe(reply, "(v)", &val) || ret < 0) + _E("Failed to get variant"); + if (reply) + g_variant_unref(reply); + free(escaped); + return val; +} + +#define SYSTEMD_DBUS_METHOD_SYSTEM_STATE "SystemState" +#define SYSTEMD_STATE_RUNNING "running" +#define SYSTEMD_STATE_DEGRADED "degraded" + +int check_system_boot_finished(void) +{ + char *state = NULL; + int ret = 0; + size_t len; + GVariant *reply = NULL; + + reply = systemd_get_manager_property(SYSTEMD_DBUS_METHOD_SYSTEM_STATE); + if (!reply) { + _E("Failed to get system state: No reply"); + goto err; + } + if (!g_variant_get_safe(reply, "s", &state)) { + _E("Failed to get system state(%s)", g_variant_get_type_string(reply)); + goto err; + } + + _I("System state=%s", state); + + len = strlen(state) + 1; + if (!strncmp(state, SYSTEMD_STATE_RUNNING, len) || + !strncmp(state, SYSTEMD_STATE_DEGRADED, len)) + ret = 1; + else + ret = 0; + +err: + if (reply) + g_variant_unref(reply); + free(state); + + return ret; +} diff --git a/src/libsystemd/libsystemd.h b/src/libsystemd/libsystemd.h new file mode 100644 index 0000000..79c9f9b --- /dev/null +++ b/src/libsystemd/libsystemd.h @@ -0,0 +1,59 @@ +/* + * libsyscommon + * + * Copyright (c) 2019 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_SYSTEMD_H__ +#define __DBUS_SYSTEMD_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int systemd_start_unit_wait_started (const char *name, + const char *suffix, + int timeout_msec); + +int systemd_stop_unit_wait_stopped (const char *name, + const char *suffix, + int timeout_msec); + +int systemd_start_unit_async (const char *name, + const char *suffix); + +int systemd_stop_unit_async (const char *name, + const char *suffix); + +GVariant *systemd_get_manager_property (const char *property); + + +GVariant *systemd_get_unit_property (const char *unit, + const char *property); + +GVariant *systemd_get_service_property (const char *unit, + const char *property); + +int check_system_boot_finished(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __DBUS_SYSTEMD_H__ */ + diff --git a/src/libsystemd/systemd-state.c b/src/libsystemd/systemd-state.c deleted file mode 100644 index 1c25575..0000000 --- a/src/libsystemd/systemd-state.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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 "shared/log.h" - -#define SYSTEMD_DBUS_METHOD_SYSTEM_STATE "SystemState" -#define SYSTEMD_STATE_RUNNING "running" -#define SYSTEMD_STATE_DEGRADED "degraded" - -int check_system_boot_finished(void) -{ - char *state = NULL; - int ret = 0; - size_t len; - GVariant *reply = NULL; - - reply = systemd_get_manager_property(SYSTEMD_DBUS_METHOD_SYSTEM_STATE); - if (!reply) { - _E("Failed to get system state: No reply"); - goto err; - } - if (!g_variant_get_safe(reply, "s", &state)) { - _E("Failed to get system state(%s)", g_variant_get_type_string(reply)); - goto err; - } - - _I("System state=%s", state); - - len = strlen(state) + 1; - if (!strncmp(state, SYSTEMD_STATE_RUNNING, len) || - !strncmp(state, SYSTEMD_STATE_DEGRADED, len)) - ret = 1; - else - ret = 0; - -err: - if (reply) - g_variant_unref(reply); - free(state); - - return ret; -} diff --git a/src/libsystemd/systemd-state.h b/src/libsystemd/systemd-state.h deleted file mode 100644 index 54b4217..0000000 --- a/src/libsystemd/systemd-state.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * libsyscommon - * - * Copyright (c) 2019 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 __SYSTEMD_STATE_H__ -#define __SYSTEMD_STATE_H__ - -#include "dbus-systemd.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int check_system_boot_finished(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif __SYSTEMD_STATE_H__