aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Čerman <ondrej.cerman@gmail.com>2019-10-23 20:48:54 +0200
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-10-24 07:52:15 -0700
commitdc665743a4d62692c18c84d57554aa0e8df1a986 (patch)
treeff05ed92bf4eac863a3bc43b79d4ce7dced5152b
parent11d610f4a44599aedcd0022a516eb2326abdd46a (diff)
Devices/storage: SMART attributes from udisks2
-rw-r--r--hardinfo/udisks2_util.c88
-rw-r--r--includes/udisks2_util.h11
-rw-r--r--modules/devices/storage.c35
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"