aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--hardinfo/udisks2_util.c235
-rw-r--r--includes/udisks2_util.h19
-rw-r--r--modules/devices.c2
-rw-r--r--modules/devices/storage.c107
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();
+}