diff options
author | Ondrej Čerman <ondrej.cerman@gmail.com> | 2019-10-23 20:48:54 +0200 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-10-24 07:52:15 -0700 |
commit | dc665743a4d62692c18c84d57554aa0e8df1a986 (patch) | |
tree | ff05ed92bf4eac863a3bc43b79d4ce7dced5152b | |
parent | 11d610f4a44599aedcd0022a516eb2326abdd46a (diff) |
Devices/storage: SMART attributes from udisks2
-rw-r--r-- | hardinfo/udisks2_util.c | 88 | ||||
-rw-r--r-- | includes/udisks2_util.h | 11 | ||||
-rw-r--r-- | modules/devices/storage.c | 35 |
3 files changed, 129 insertions, 5 deletions
diff --git a/hardinfo/udisks2_util.c b/hardinfo/udisks2_util.c index 8aa54f72..11e091b9 100644 --- a/hardinfo/udisks2_util.c +++ b/hardinfo/udisks2_util.c @@ -201,7 +201,8 @@ GSList* get_block_dev_paths_from_sysfs(){ } GSList* udisks2_drives_func_caller(GDBusConnection* conn, - gpointer (*func)(const char*, GDBusProxy*, GDBusProxy*)) { + gpointer (*func)(const char*, GDBusProxy*, + GDBusProxy*, const char*)) { GDBusProxy *block_proxy, *drive_proxy; GVariant *block_v, *v; GSList *result_list = NULL, *block_dev_list, *node; @@ -262,7 +263,7 @@ GSList* udisks2_drives_func_caller(GDBusConnection* conn, if (error == NULL) { // call requested function - output = func(block_dev, block_proxy, drive_proxy); + output = func(block_dev, block_proxy, drive_proxy, drive_path); if (output != NULL){ result_list = g_slist_append(result_list, output); @@ -322,6 +323,10 @@ udiskt* udiskt_new() { return g_new0(udiskt, 1); } +udisksa* udisksa_new() { + return g_new0(udisksa, 1); +} + udiskp* udiskp_new() { return g_new0(udiskp, 1); } @@ -330,6 +335,7 @@ udiskd* udiskd_new() { return g_new0(udiskd, 1); } + void udiskt_free(udiskt *u) { if (u) { g_free(u->drive); @@ -337,6 +343,14 @@ void udiskt_free(udiskt *u) { } } +void udisksa_free(udisksa *u) { + if (u) { + g_free(u->identifier); + udisksa_free(u->next); + g_free(u); + } +} + void udiskp_free(udiskp *u) { if (u) { g_free(u->block); @@ -358,12 +372,14 @@ void udiskd_free(udiskd *u) { g_free(u->connection_bus); g_free(u->partition_table); udiskp_free(u->partitions); + udisksa_free(u->smart_attributes); g_free(u->media); g_strfreev(u->media_compatibility); g_free(u); } } + udiskp* get_udisks2_partition_info(const gchar *part_path) { GVariant *v; GDBusProxy *proxy; @@ -414,7 +430,8 @@ udiskp* get_udisks2_partition_info(const gchar *part_path) { return partition; } -gpointer get_udisks2_temp(const char *blockdev, GDBusProxy *block, GDBusProxy *drive){ +gpointer get_udisks2_temp(const char *blockdev, GDBusProxy *block, + GDBusProxy *drive, const char *drivepath){ GVariant *v; gboolean smart_enabled = FALSE; udiskt* disk_temp = NULL; @@ -449,7 +466,69 @@ gpointer get_udisks2_temp(const char *blockdev, GDBusProxy *block, GDBusProxy *d return disk_temp; } -gpointer get_udisks2_drive_info(const char *blockdev, GDBusProxy *block, GDBusProxy *drive) { +gchar* get_udisks2_smart_attributes(udiskd* dsk, const char *drivepath){ + GDBusProxy *proxy; + GVariant *options, *v, *v2; + GVariantIter *iter; + GError *error = NULL; + const char* aidenf; + guint8 aid; + gint16 avalue, aworst, athreshold; + gint64 pretty; + udisksa *lastp = NULL, *p; + + proxy = g_dbus_proxy_new_sync(udisks2_conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + UDISKS2_INTERFACE, drivepath, + UDISKS2_DRIVE_ATA_INTERFACE, NULL, &error); + + options = g_variant_new_parsed("@a{sv} { %s: <true> }", + "auth.no_user_interaction"); + if (error != NULL){ + g_error_free (error); + return NULL; + } + + v = g_dbus_proxy_call_sync(proxy, "SmartGetAttributes", + g_variant_new_tuple(&options, 1), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + g_object_unref(proxy); + + if (error != NULL){ + g_error_free (error); + g_object_unref(proxy); + return NULL; + } + + v2 = g_variant_get_child_value(v, 0); + iter = g_variant_iter_new(v2); + + // id(y), identifier(s), flags(q), value(i), worst(i), threshold(i), + // pretty(x), pretty_unit(i), expansion(a{sv}) + while (g_variant_iter_loop (iter, "(ysqiiixia{sv})", &aid, &aidenf, NULL, &avalue, &aworst, &athreshold, NULL, NULL, NULL)){ + p = udisksa_new(); + p->id = aid; + p->identifier = g_strdup(aidenf); + p->value = avalue; + p->worst = aworst; + p->threshold = athreshold; + p->next = NULL; + + if (lastp == NULL) + dsk->smart_attributes = p; + else + lastp->next = p; + + lastp = p; + } + g_variant_iter_free (iter); + g_variant_unref(v2); + g_variant_unref(v); + + return NULL; +} + +gpointer get_udisks2_drive_info(const char *blockdev, GDBusProxy *block, + GDBusProxy *drive, const char *drivepath) { GVariant *v; GVariantIter *iter; const gchar *str, *part; @@ -573,6 +652,7 @@ gpointer get_udisks2_drive_info(const char *blockdev, GDBusProxy *block, GDBusPr u->smart_failing = g_variant_get_boolean(v); g_variant_unref(v); } + get_udisks2_smart_attributes(u, drivepath); } v = get_dbus_property(block, UDISKS2_PART_TABLE_INTERFACE, "Type"); diff --git a/includes/udisks2_util.h b/includes/udisks2_util.h index 813825cb..acd2282f 100644 --- a/includes/udisks2_util.h +++ b/includes/udisks2_util.h @@ -9,6 +9,15 @@ typedef struct udiskp { struct udiskp* next; } udiskp; +typedef struct udisksa { + guint8 id; + gchar *identifier; + gint value; + gint worst; + gint threshold; + struct udisksa* next; +} udisksa; + typedef struct udiskd { gchar *model; gchar *vendor; @@ -33,6 +42,7 @@ typedef struct udiskd { guint64 smart_poweron; gint64 smart_bad_sectors; gint32 smart_temperature; + udisksa *smart_attributes; vendor_list vendors; } udiskd; @@ -40,7 +50,6 @@ typedef struct udiskt { gchar *drive; gint32 temperature; } udiskt; - void udisks2_init(); void udisks2_shutdown(); GSList *get_udisks2_temps(); diff --git a/modules/devices/storage.c b/modules/devices/storage.c index def39839..cedaed85 100644 --- a/modules/devices/storage.c +++ b/modules/devices/storage.c @@ -29,6 +29,7 @@ gboolean __scan_udisks2_devices(void) { GSList *node, *drives; udiskd *disk; udiskp *part; + udisksa *attrib; gchar *udisks2_storage_list = NULL, *features = NULL, *moreinfo = NULL; gchar *devid, *label, *size, *tmp = NULL, *media_comp = NULL; const gchar *url, *vendor_str, *media_label, *icon, *media_curr = NULL; @@ -199,6 +200,40 @@ gboolean __scan_udisks2_devices(void) { disk->smart_bad_sectors, disk->smart_poweron/(60*60*24), (disk->smart_poweron/60/60) % 24, disk->smart_temperature); + + if (disk->smart_attributes != NULL) { + moreinfo = h_strdup_cprintf(_("[S.M.A.R.T. Attributes]\n" + "Attribute=Normalized Value / Worst / Threshold\n"), + moreinfo); + + attrib = disk->smart_attributes; + + while (attrib != NULL){ + tmp = g_strdup(""); + if (attrib->value != -1) + tmp = h_strdup_cprintf("%3d", tmp, attrib->value); + else + tmp = h_strdup_cprintf("???", tmp); + + if (attrib->worst != -1) + tmp = h_strdup_cprintf(" / %3d", tmp, attrib->worst); + else + tmp = h_strdup_cprintf(" / ???", tmp); + + if (attrib->threshold != -1) + tmp = h_strdup_cprintf(" / %3d", tmp, attrib->threshold); + else + tmp = h_strdup_cprintf(" / ???", tmp); + + moreinfo = h_strdup_cprintf(_("(%d) %s=%s\n"), + moreinfo, + attrib->id, + attrib->identifier, + tmp); + g_free(tmp); + attrib = attrib->next; + } + } } if (disk->partition_table || disk->partitions) { moreinfo = h_strdup_cprintf(_("[Partition table]\n" |