Files
fastfetch/src/common/impl/dbus.c
T

338 lines
10 KiB
C
Raw Normal View History

2026-01-06 09:48:38 +08:00
#include "common/dbus.h"
2023-01-24 10:39:33 +01:00
2023-01-26 22:08:55 +01:00
#ifdef FF_HAVE_DBUS
2026-10-03 14:27:24 +08:00
#include "common/debug.h"
#include "common/thread.h"
2026-05-28 15:58:08 +08:00
#include "common/strutil.h"
2023-01-24 10:39:33 +01:00
2026-03-29 09:28:49 +08:00
static bool loadLibSymbols(FFDBusLibrary* lib) {
2024-09-04 15:28:35 +08:00
FF_LIBRARY_LOAD(dbus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
2023-01-24 10:39:33 +01:00
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_append_args, false)
2023-01-24 10:39:33 +01:00
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_unref, false)
2026-07-10 18:08:04 +08:00
dbus = nullptr; // don't auto dlclose
2023-01-24 10:39:33 +01:00
return true;
}
2026-03-29 09:28:49 +08:00
static const FFDBusLibrary* loadLib(void) {
2023-01-24 10:39:33 +01:00
static FFDBusLibrary lib;
static bool loaded = false;
static bool loadSuccess = false;
2026-03-29 09:28:49 +08:00
if (!loaded) {
2023-01-24 10:39:33 +01:00
loaded = true;
loadSuccess = loadLibSymbols(&lib);
2023-01-24 10:39:33 +01:00
}
2026-07-10 18:08:04 +08:00
return loadSuccess ? &lib : nullptr;
2023-01-24 10:39:33 +01:00
}
2026-03-29 09:28:49 +08:00
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data) {
data->lib = loadLib();
2026-07-10 18:08:04 +08:00
if (data->lib == nullptr) {
2026-10-03 14:27:24 +08:00
FF_DEBUG("libdbus-1 could not be loaded");
2023-01-24 10:39:33 +01:00
return "Failed to load DBus library";
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
2026-07-10 18:08:04 +08:00
data->connection = data->lib->ffdbus_bus_get(busType, nullptr);
if (data->connection == nullptr) {
2026-10-03 14:27:24 +08:00
FF_DEBUG("dbus_bus_get(busType=%d) returned no connection", (int) busType);
2023-01-24 10:39:33 +01:00
return "Failed to connect to DBus";
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
2026-07-10 18:08:04 +08:00
return nullptr;
2023-01-24 10:39:33 +01:00
}
2026-03-29 09:28:49 +08:00
void ffDBusDestroyData(FFDBusData* data) {
2026-07-10 18:08:04 +08:00
if (data->connection != nullptr) {
data->lib->ffdbus_connection_unref(data->connection);
2026-07-10 18:08:04 +08:00
data->connection = nullptr;
}
}
2026-03-29 09:28:49 +08:00
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) {
2023-01-24 10:39:33 +01:00
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH) {
2026-07-10 18:08:04 +08:00
const char* value = nullptr;
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
2026-03-29 09:28:49 +08:00
if (!ffStrSet(value)) {
2023-01-24 10:39:33 +01:00
return false;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
ffStrbufAppendS(result, value);
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_BYTE) {
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
ffStrbufAppendC(result, (char) value);
2026-04-27 22:11:34 +08:00
return true;
}
2026-03-29 09:28:49 +08:00
if (argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) {
2023-01-24 10:39:33 +01:00
return false;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_VARIANT) {
return ffDBusGetString(dbus, &subIter, result);
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
2026-03-29 09:28:49 +08:00
// At this point we have an array
2023-01-24 10:39:33 +01:00
2026-04-27 22:11:34 +08:00
int subArgType = dbus->lib->ffdbus_message_iter_get_arg_type(&subIter);
if (subArgType == DBUS_TYPE_INVALID) {
return false;
}
if (subArgType == DBUS_TYPE_BYTE) {
while (true) {
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(&subIter, &value);
ffStrbufAppendC(result, (char) value);
if (!dbus->lib->ffdbus_message_iter_next(&subIter)) {
break;
}
}
return true;
}
2023-01-24 10:39:33 +01:00
bool foundAValue = false;
2026-03-29 09:28:49 +08:00
while (true) {
if (ffDBusGetString(dbus, &subIter, result)) {
2023-01-24 10:39:33 +01:00
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
2026-03-29 09:28:49 +08:00
if (!dbus->lib->ffdbus_message_iter_next(&subIter)) {
break;
2026-03-29 09:28:49 +08:00
} else {
continue;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
}
2026-03-29 09:28:49 +08:00
if (foundAValue) {
2023-01-24 10:39:33 +01:00
ffStrbufSubstrBefore(result, result->length - 2);
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
return foundAValue;
}
2026-03-29 09:28:49 +08:00
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result) {
2023-01-24 10:39:33 +01:00
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_BOOLEAN) {
2023-01-24 10:39:33 +01:00
dbus_bool_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value != 0;
return true;
}
2026-03-29 09:28:49 +08:00
if (argType != DBUS_TYPE_VARIANT) {
2023-01-24 10:39:33 +01:00
return false;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetBool(dbus, &subIter, result);
}
2026-05-11 23:24:45 +08:00
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint64_t* result) {
2023-01-24 10:39:33 +01:00
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_BYTE) {
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
2023-01-24 10:39:33 +01:00
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_UINT16) {
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_UINT32) {
2026-05-11 23:24:45 +08:00
uint32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_UINT64) {
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
}
2026-03-29 09:28:49 +08:00
if (argType != DBUS_TYPE_VARIANT) {
return false;
2026-03-29 09:28:49 +08:00
}
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetUint(dbus, &subIter, result);
}
2026-05-11 23:24:45 +08:00
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int64_t* result) {
2025-09-04 09:35:52 +08:00
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_INT16) {
2025-09-04 09:35:52 +08:00
int16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_INT32) {
2026-05-11 23:24:45 +08:00
int32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_INT64) {
2025-09-04 09:35:52 +08:00
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_BYTE) {
2025-09-04 09:35:52 +08:00
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_UINT16) {
2025-09-04 09:35:52 +08:00
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
2026-04-27 22:11:34 +08:00
*result = (int32_t) value;
2025-09-04 09:35:52 +08:00
return true;
}
2026-03-29 09:28:49 +08:00
if (argType == DBUS_TYPE_UINT32) {
2026-04-27 22:11:34 +08:00
uint32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
2026-05-11 23:24:45 +08:00
*result = (int32_t) value;
return true;
}
if (argType == DBUS_TYPE_UINT64) {
uint64_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
if (value > INT64_MAX) {
2026-04-27 22:11:34 +08:00
return false;
}
2026-05-11 23:24:45 +08:00
*result = (int64_t) value;
2025-09-04 09:35:52 +08:00
return true;
}
2026-03-29 09:28:49 +08:00
if (argType != DBUS_TYPE_VARIANT) {
2025-09-04 09:35:52 +08:00
return false;
2026-03-29 09:28:49 +08:00
}
2025-09-04 09:35:52 +08:00
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetInt(dbus, &subIter, result);
}
2026-03-29 09:28:49 +08:00
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2) {
2023-01-24 10:39:33 +01:00
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
2026-07-10 18:08:04 +08:00
if (message == nullptr) {
return nullptr;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
2026-03-29 09:28:49 +08:00
if (arg1) {
if (arg2) {
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_STRING, &arg2, DBUS_TYPE_INVALID);
2026-03-29 09:28:49 +08:00
} else {
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_INVALID);
2026-03-29 09:28:49 +08:00
}
}
2026-07-10 18:08:04 +08:00
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, nullptr);
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_unref(message);
return reply;
}
2026-03-29 09:28:49 +08:00
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property) {
2023-01-24 10:39:33 +01:00
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
2026-07-10 18:08:04 +08:00
if (message == nullptr) {
return nullptr;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_append_args(message,
2026-03-29 09:28:49 +08:00
DBUS_TYPE_STRING,
&interface,
DBUS_TYPE_STRING,
&property,
DBUS_TYPE_INVALID);
2023-01-24 10:39:33 +01:00
2026-07-10 18:08:04 +08:00
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, nullptr);
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_unref(message);
return reply;
}
2026-03-29 09:28:49 +08:00
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result) {
2023-01-24 10:39:33 +01:00
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
2026-07-10 18:08:04 +08:00
if (reply == nullptr) {
2024-04-17 19:00:45 +08:00
return false;
2026-03-29 09:28:49 +08:00
}
2023-01-24 10:39:33 +01:00
DBusMessageIter rootIterator;
2026-03-29 09:28:49 +08:00
if (!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) {
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_unref(reply);
2024-04-17 19:00:45 +08:00
return false;
2023-01-24 10:39:33 +01:00
}
bool ret = ffDBusGetString(dbus, &rootIterator, result);
2023-01-24 10:39:33 +01:00
dbus->lib->ffdbus_message_unref(reply);
2024-04-17 19:00:45 +08:00
return ret;
2023-01-24 10:39:33 +01:00
}
2023-01-26 22:08:55 +01:00
2026-05-11 23:24:45 +08:00
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint64_t* result) {
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
2026-07-10 18:08:04 +08:00
if (reply == nullptr) {
return false;
2026-03-29 09:28:49 +08:00
}
DBusMessageIter rootIterator;
2026-03-29 09:28:49 +08:00
if (!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) {
dbus->lib->ffdbus_message_unref(reply);
return false;
}
bool ret = ffDBusGetUint(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
return ret;
}
2026-03-29 09:28:49 +08:00
#endif // FF_HAVE_DBUS