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(); +}  | 
