diff options
author | Ondrej Čerman <ondrej.cerman@gmail.com> | 2018-11-27 23:25:42 +0100 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2018-11-30 04:57:38 -0800 |
commit | bca05f203758173c227aed228463fdddefcd8c6a (patch) | |
tree | 760dc8abb94d5279f62990ff9e4d41e97fe7bda3 | |
parent | 0f3cf14d062ccd89467ecd933081b18a4e6636b9 (diff) |
devices/storage: added udisks2 support
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | hardinfo/udisks2_util.c | 235 | ||||
-rw-r--r-- | includes/udisks2_util.h | 19 | ||||
-rw-r--r-- | modules/devices.c | 2 | ||||
-rw-r--r-- | modules/devices/storage.c | 107 |
5 files changed, 359 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e82e7b..b2f82fa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,6 +235,7 @@ add_executable(hardinfo hardinfo/dt_util.c hardinfo/x_util.c hardinfo/gpu_util.c + hardinfo/udisks2_util.c shell/callbacks.c shell/iconcache.c shell/menu.c @@ -268,6 +269,7 @@ add_executable(hardinfo hardinfo/dt_util.c hardinfo/x_util.c hardinfo/gpu_util.c + hardinfo/udisks2_util.c shell/callbacks.c shell/iconcache.c shell/menu.c diff --git a/hardinfo/udisks2_util.c b/hardinfo/udisks2_util.c new file mode 100644 index 00000000..bf7948b3 --- /dev/null +++ b/hardinfo/udisks2_util.c @@ -0,0 +1,235 @@ +#include <gio/gio.h> +#include "udisks2_util.h" +#include "hardinfo.h" + +#define UDISKS2_INTERFACE "org.freedesktop.UDisks2" +#define UDISKS2_MANAGER_INTERFACE "org.freedesktop.UDisks2.Manager" +#define UDISKS2_BLOCK_INTERFACE "org.freedesktop.UDisks2.Block" +#define UDISKS2_DRIVE_INTERFACE "org.freedesktop.UDisks2.Drive" +#define UDISKS2_DRIVE_ATA_INTERFACE "org.freedesktop.UDisks2.Drive.Ata" +#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" +#define UDISKS2_MANAGER_OBJ_PATH "/org/freedesktop/UDisks2/Manager" +#define UDISKS2_BLOCK_DEVICES_PATH "/org/freedesktop/UDisks2/block_devices" + +GDBusConnection* udisks2_conn = NULL; + +GVariant* get_dbus_property(GDBusProxy* proxy, const gchar *interface, + const gchar *property) { + GVariant *result, *v = NULL; + GError *error = NULL; + + result = g_dbus_proxy_call_sync(proxy, "Get", + g_variant_new ("(ss)", interface, property), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (error != NULL) { + g_error_free (error); + return NULL; + } + + g_variant_get(result, "(v)", &v); + g_variant_unref(result); + return v; +} + +GDBusProxy* get_udisks2_drive_proxy(GDBusConnection *conn, const gchar* blockdev_name) { + GDBusProxy *proxy; + GVariant *v; + GError *error = NULL; + gchar *path; + const gchar *drive_path; + + // get block device proxy + path = g_strdup_printf("%s/%s", UDISKS2_BLOCK_DEVICES_PATH, blockdev_name); + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + UDISKS2_INTERFACE, path, + DBUS_PROPERTIES_INTERFACE, NULL, &error); + g_free(path); + path = NULL; + if (error != NULL) { + g_error_free (error); + g_object_unref(proxy); + return NULL; + } + + // get drive object path + v = get_dbus_property(proxy, UDISKS2_BLOCK_INTERFACE, "Drive"); + if (v) { + drive_path = g_variant_get_string(v, NULL); + if (strcmp(drive_path, "/") != 0) { + path = g_strdup(drive_path); + } + g_variant_unref(v); + } + g_object_unref(proxy); + proxy = NULL; + + if (path == NULL) + return NULL; + + // get drive proxy + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + UDISKS2_INTERFACE, path, + DBUS_PROPERTIES_INTERFACE, NULL, &error); + g_free(path); + if (error != NULL) { + g_error_free (error); + return NULL; + } + + return proxy; +} + +GDBusConnection* get_udisks2_connection(void) { + GDBusConnection *conn; + GDBusProxy *proxy; + GError *error = NULL; + GVariant *result = NULL; + + // connection to system bus + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error != NULL) { + g_error_free (error); + return NULL; + } + + // let's check if udisks2 is responding + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + UDISKS2_INTERFACE, UDISKS2_MANAGER_OBJ_PATH, + DBUS_PROPERTIES_INTERFACE, NULL, &error); + if (error != NULL) { + g_error_free (error); + g_object_unref(conn); + return NULL; + } + + result = get_dbus_property(proxy, UDISKS2_MANAGER_INTERFACE, "Version"); + g_object_unref(proxy); + if (error != NULL) { + g_error_free (error); + return NULL; + } + + // OK, let's return connection to system bus + g_variant_unref(result); + return conn; +} + +udiskd *udiskd_new() { + return g_new0(udiskd, 1); +} + +void udiskd_free(udiskd *u) { + if (u) { + g_free(u->block_dev); + g_free(u->media); + g_free(u->media_compatibility); + g_free(u); + } +} + +udiskd *get_udisks2_drive_info(const gchar *blockdev) { + GDBusProxy *drive; + GVariant *v; + const gchar *str; + udiskd *u; + + drive = get_udisks2_drive_proxy(udisks2_conn, blockdev); + if (!drive){ + return NULL; + } + + u = udiskd_new(); + u->block_dev = g_strdup(blockdev); + + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "Serial"); + if (v){ + u->serial = g_variant_dup_string(v, NULL); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "RotationRate"); + if (v){ + u->rotation_rate = g_variant_get_int32(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "Size"); + if (v){ + u->size = g_variant_get_uint64(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "Media"); + if (v){ + str = g_variant_get_string(v, NULL); + if (strcmp(str, "") != 0) { + u->media = g_strdup(str); + } + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "MediaCompatibility"); + if (v){ + GVariantIter *iter; + g_variant_get(v, "as", &iter); + while (g_variant_iter_loop (iter, "s", &str)){ + if (u->media_compatibility == NULL){ + u->media_compatibility = g_strdup(str); + } + else{ + u->media_compatibility = h_strdup_cprintf(", %s", u->media_compatibility, str); + } + } + g_variant_iter_free (iter); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "Ejectable"); + if (v){ + u->ejectable = g_variant_get_boolean(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_INTERFACE, "Removable"); + if (v){ + u->removable = g_variant_get_boolean(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_ATA_INTERFACE, "SmartEnabled"); + if (v){ + u->smart_enabled = g_variant_get_boolean(v); + g_variant_unref(v); + } + if (u->smart_enabled){ + v = get_dbus_property(drive, UDISKS2_DRIVE_ATA_INTERFACE, "SmartPowerOnSeconds"); + if (v){ + u->smart_poweron = g_variant_get_uint64(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_ATA_INTERFACE, "SmartNumBadSectors"); + if (v){ + u->smart_bad_sectors = g_variant_get_int64(v); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_ATA_INTERFACE, "SmartTemperature"); + if (v){ + u->smart_temperature = (gint) (g_variant_get_double(v) - 273.15); + g_variant_unref(v); + } + v = get_dbus_property(drive, UDISKS2_DRIVE_ATA_INTERFACE, "SmartFailing"); + if (v){ + u->smart_failing = g_variant_get_boolean(v); + g_variant_unref(v); + } + } + + g_object_unref(drive); + return u; +} + +gboolean udisks2_init(){ + udisks2_conn = get_udisks2_connection(); + return (udisks2_conn != NULL); +} + +void udisks2_shutdown(){ + if (udisks2_conn != NULL){ + g_object_unref(udisks2_conn); + udisks2_conn = NULL; + } +} diff --git a/includes/udisks2_util.h b/includes/udisks2_util.h new file mode 100644 index 00000000..86417095 --- /dev/null +++ b/includes/udisks2_util.h @@ -0,0 +1,19 @@ +typedef struct udiskd { + gchar *block_dev; + gchar *serial; + gboolean ejectable; + gboolean removable; + gint32 rotation_rate; + gint64 size; + gchar *media; + gchar *media_compatibility; + gboolean smart_enabled; + gboolean smart_failing; + guint64 smart_poweron; + gint64 smart_bad_sectors; + gint32 smart_temperature; +} udiskd; + +gboolean udisks2_init(); +void udisks2_shutdown(); +udiskd *get_udisks2_drive_info(const gchar *blockdev); diff --git a/modules/devices.c b/modules/devices.c index 4439c058..d875aa93 100644 --- a/modules/devices.c +++ b/modules/devices.c @@ -791,12 +791,14 @@ void hi_module_init(void) init_memory_labels(); init_cups(); sensors_init(); + storage_init(); } void hi_module_deinit(void) { moreinfo_del_with_prefix("DEV"); sensors_shutdown(); + storage_shutdown(); g_hash_table_destroy(memlabels); g_module_close(cups); } diff --git a/modules/devices/storage.c b/modules/devices/storage.c index d6192437..26b10097 100644 --- a/modules/devices/storage.c +++ b/modules/devices/storage.c @@ -20,12 +20,95 @@ #include "hardinfo.h" #include "devices.h" +#include "udisks2_util.h" gchar *storage_icons = NULL; +gboolean udisks2_available = FALSE; + +gboolean print_udisks2_info(const gchar *blockdev_name, gchar **str) { + udiskd *disk; + gchar *features = NULL; + + disk = get_udisks2_drive_info(blockdev_name); + if (disk == NULL) { + return FALSE; + } + + features = h_strdup_cprintf("%s", features, disk->removable ? _("Removable"): _("Fixed")); + if (disk->ejectable) { + features = h_strdup_cprintf(", %s", features, _("Ejectable")); + } + if (disk->smart_enabled) { + features = h_strdup_cprintf(", %s", features, _("Smart monitoring")); + } + + *str = h_strdup_cprintf(_( "Block Device=%s\n" + "Serial=%s\n" + "Size=%s\n" + "Features=%s\n"), + *str, + disk->block_dev, + disk->serial, + size_human_readable((gfloat) disk->size), + features); + + if (disk->rotation_rate > 0){ + *str = h_strdup_cprintf(_("Rotation Rate=%d\n"), *str, disk->rotation_rate); + } + if (disk->media_compatibility || disk->media){ + *str = h_strdup_cprintf(_( "Media=%s\n" + "Media compatibility=%s\n"), + *str, + disk->media ? disk->media : _("(None)"), + disk->media_compatibility ? disk->media_compatibility : _("(Unknown)")); + } + if (disk->smart_enabled){ + *str = h_strdup_cprintf(_( "[Smart monitoring]\n" + "Status=%s\n" + "Bad Sectors=%ld\n" + "Power on time=%d days %d hours\n" + "Temperature=%d°C\n"), + *str, + disk->smart_failing ? _("Failing"): _("OK"), + disk->smart_bad_sectors, + disk->smart_poweron/(60*60*24), (disk->smart_poweron/60/60) % 24, + disk->smart_temperature); + } + + g_free(features); + udiskd_free(disk); + + return TRUE; +} + +void print_scsi_dev_info(gint controller, gint channel, gint id, gint lun, gchar **str) { + gchar *path; + GDir *dir; + const gchar *entry; + + path = g_strdup_printf("/sys/class/scsi_device/%d:%d:%d:%d/device/block/", controller, channel, id, lun); + dir = g_dir_open(path, 0, NULL); + if (!dir){ + g_free(path); + return; + } + + if ((entry = g_dir_read_name(dir))) { + gboolean udisk_info = FALSE; + if (udisks2_available) { + udisk_info = print_udisks2_info(entry, str); + } + if (!udisk_info) { + // TODO: fallback + } + } + + g_dir_close(dir); + g_free(path); +} /* SCSI support by Pascal F.Martin <pascalmartin@earthlink.net> */ -void -__scan_scsi_devices(void) +void __scan_scsi_devices(void) { FILE *proc_scsi; gchar buffer[256], *buf; @@ -127,14 +210,18 @@ __scan_scsi_devices(void) } strhash = h_strdup_cprintf(_("Type=%s\n" - "Revision=%s\n" - "[SCSI Controller]\n" + "Revision=%s\n"), + strhash, + type, + revision); + + print_scsi_dev_info(scsi_controller, scsi_channel, scsi_id, scsi_lun, &strhash); + + strhash = h_strdup_cprintf(_("[SCSI Controller]\n" "Controller=scsi%d\n" "Channel=%d\n" "ID=%d\n" "LUN=%d\n"), strhash, - type, - revision, scsi_controller, scsi_channel, scsi_id, @@ -376,3 +463,11 @@ void __scan_ide_devices(void) g_free(ide_storage_list); } } + +void storage_init(void) { + udisks2_available = udisks2_init(); +} + +void storage_shutdown(void) { + udisks2_shutdown(); +} |