Rework ATA SMART handling
authorDavid Zeuthen <davidz@redhat.com>
Sun, 23 Aug 2009 18:12:49 +0000 (14:12 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Sun, 23 Aug 2009 18:12:49 +0000 (14:12 -0400)
Basically make everything a lot simpler. Also don't store blobs in a
database. For now at least - we might want to add that feature back at
some point.

12 files changed:
configure.ac
data/org.freedesktop.DeviceKit.Disks.Device.xml
src/Makefile.am
src/devkit-disks-ata-smart-db.c [deleted file]
src/devkit-disks-ata-smart-db.h [deleted file]
src/devkit-disks-daemon.c
src/devkit-disks-daemon.h
src/devkit-disks-device-private.c
src/devkit-disks-device-private.h
src/devkit-disks-device.c
tools/Makefile.am
tools/devkit-disks.c

index c5a65dd..57dab50 100644 (file)
@@ -109,16 +109,6 @@ if test "x$GCC" = "xyes"; then
   changequote([,])dnl
 fi
 
-have_zlib="false"
-AC_CHECK_LIB([z], [compress2], [have_zlib="true"])
-if test x$have_zlib != "xtrue"; then
-  AC_MSG_ERROR([zlib is needed])
-fi
-ZLIB_CFLAGS=
-ZLIB_LIBS="-lz"
-AC_SUBST(ZLIB_CFLAGS)
-AC_SUBST(ZLIB_LIBS)
-
 have_sgutils="false"
 AC_CHECK_LIB([sgutils2], [sg_ll_inquiry], have_sgutils="true")
 if test x$have_sgutils != "xtrue"; then
@@ -130,10 +120,6 @@ AC_SUBST(SGUTILS_CFLAGS)
 AC_SUBST(SGUTILS_LIBS)
 
 
-PKG_CHECK_MODULES(SQLITE3, [sqlite3])
-AC_SUBST(SQLITE3_CFLAGS)
-AC_SUBST(SQLITE3_LIBS)
-
 PKG_CHECK_MODULES(GUDEV, [gudev-1.0 >= 001])
 AC_SUBST(GUDEV_CFLAGS)
 AC_SUBST(GUDEV_LIBS)
index b770896..c1f2775 100644 (file)
 
     <!-- ************************************************************ -->
 
-    <method name="DriveAtaSmartGetHistoricalData">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg name="since" direction="in" type="t">
-        <doc:doc><doc:summary>
-            Don't fetch data collected earlier than this point
-            in time (seconds since the Epoch Jan 1, 1970 0:00 UTC).
-        </doc:summary></doc:doc>
-      </arg>
-      <arg name="until" direction="in" type="t">
-        <doc:doc><doc:summary>
-            Don't fetch data collected later than this point in
-            time (seconds since the Epoch Jan 1, 1970 0:00 UTC). If 0 is
-            passed the current time will be used.
-        </doc:summary></doc:doc>
-      </arg>
-      <arg name="spacing" direction="in" type="t">
-        <doc:doc><doc:summary>
-            The minimum spacing (in seconds) between two data points or 0
-            to get all data points between @since and @until.
-        </doc:summary></doc:doc>
-      </arg>
-      <arg name="data" direction="out" type="a(tbbbbdta(usubbybybybbbutay))">
-        <doc:doc><doc:summary>
-            An array of historical data sorted by collection date. Each element contains
-            the following members (TODO).
-        </doc:summary></doc:doc>
-      </arg>
-      <doc:doc>
-        <doc:description>
-          <doc:para>
-            Retrieves historical ATA SMART data from the drive in the
-            given time interval. Note that this is data collected and
-            stored by the host as ATA SMART capable devices cannot
-            store or return historical data by themselves.
-          </doc:para>
-        </doc:description>
-        <doc:permission>
-          The caller will need one of the following PolicyKit authorizations:
-          <doc:list>
-            <doc:item>
-              <doc:term>org.freedesktop.devicekit.disks.drive-ata-smart-retrieve-historical-data</doc:term>
-              <doc:definition>To retrieve historical ATA SMART data</doc:definition>
-            </doc:item>
-          </doc:list>
-        </doc:permission>
-        <doc:errors>
-          <doc:error name="&ERROR_NOT_AUTHORIZED;">if the caller lacks the appropriate PolicyKit authorization</doc:error>
-          <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error>
-          <doc:error name="&ERROR_CANCELLED;">if the job was cancelled</doc:error>
-        </doc:errors>
-      </doc:doc>
-    </method>
-
-    <!-- ************************************************************ -->
-
     <method name="DriveAtaSmartInitiateSelftest">
       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
 
 
     <property name="drive-ata-smart-is-available" type="b" access="read">
       <doc:doc><doc:description><doc:para>
-            TRUE only if drive is capable of reporting
-            <doc:ulink url="http://en.wikipedia.org/wiki/S.M.A.R.T">ATA SMART</doc:ulink>
-            data.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-is-failing" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Set to TRUE if ATA SMART indicates that the disk is failing, TRUE otherwise.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero and the property
-            <doc:ref type="property" to="Device:drive-ata-smart-status-valid">drive-ata-smart-status-valid</doc:ref>
-            is TRUE.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-is-failing-valid" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Set to TRUE only if the property
-            <doc:ref type="property" to="Device:drive-ata-smart-status">drive-ata-smart-status</doc:ref>
-            is valid.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-has-bad-sectors" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Set to TRUE if ATA SMART indicates that one or more sectors are bad, TRUE otherwise.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-has-bad-attributes" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Set to TRUE if ATA SMART indicates that one or more attributes are exceeding their threshold, TRUE otherwise.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-temperature-kelvin" type="d" access="read">
-      <doc:doc><doc:description><doc:para>
-            Temperature of the drive in kelvin or 0 if unknown.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-power-on-seconds" type="t" access="read">
-      <doc:doc><doc:description><doc:para>
-            Seconds the drive has been powered on or 0 if unknown.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
+            TRUE if the disk is capable of reporting SMART data, FALSE otherwise.
       </doc:para></doc:description></doc:doc>
     </property>
     <property name="drive-ata-smart-time-collected" type="t" access="read">
       <doc:doc><doc:description><doc:para>
             The point in time (seconds since the Epoch Jan 1, 1970
-            0:00 UTC) when ATA SMART data was collected. If data
-            was never collected, this property will assume the value
-            0.  This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-is-available">drive-ata-smart-is-available</doc:ref>
-            is TRUE.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-offline-data-collection-status" type="u" access="read">
-      <doc:doc><doc:description><doc:para>
-            Offline data collection status (TODO: specify values).
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-offline-data-collection-seconds" type="u" access="read">
-      <doc:doc><doc:description><doc:para>
-            Number of seconds needed to perform offline data collection status.
+            0:00 UTC) when ATA SMART data was collected.
             This property is only valid if
             <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
             is greater than zero.
       </doc:para></doc:description></doc:doc>
     </property>
-    <property name="drive-ata-smart-self-test-execution-status" type="u" access="read">
+    <property name="drive-ata-smart-status" type="s" access="read">
       <doc:doc><doc:description><doc:para>
-            Current status of self test (TODO: specify values).
+            The overall assessment for the disk. Is one of the following strings
+            <quote>GOOD</quote>,
+            <quote>BAD_ATTRIBUTES_IN_THE_PAST</quote> (At least one pre-fail attribute is exceeded its threshold in the past),
+            <quote>BAD_SECTOR</quote> (At least one bad sector),
+            <quote>BAD_ATTRIBUTE_NOW</quote> (At least one pre-fail attribute is exceeding its threshold now),
+            <quote>BAD_SECTOR_MANY</quote> (Many bad sectors)),
+            <quote>BAD_STATUS</quote> (Smart Self Assessment negative)
+            or empty if some error occured trying to determine the result.
             This property is only valid if
             <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
             is greater than zero.
       </doc:para></doc:description></doc:doc>
     </property>
-    <property name="drive-ata-smart-self-test-execution-percent-remaining" type="u" access="read">
+    <property name="drive-ata-smart-blob" type="ay" access="read">
       <doc:doc><doc:description><doc:para>
-            The progress of an ongoing self test or 0 if no self test is in progress.
+            A blob containing the ATA SMART data. This blob can be used with libatasmart to get
+            more information.
             This property is only valid if
             <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
             is greater than zero.
       </doc:para></doc:description></doc:doc>
     </property>
-    <property name="drive-ata-smart-short-and-extended-self-test-available" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Whether the short and extended self-tests are available.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-conveyance-self-test-available" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Whether the conveyance self-test is available.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-start-self-test-available" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Whether the start self-test is available.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-abort-self-test-available" type="b" access="read">
-      <doc:doc><doc:description><doc:para>
-            Whether the abort self-test is available.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-
-    <property name="drive-ata-smart-short-self-test-polling-minutes" type="u" access="read">
-      <doc:doc><doc:description><doc:para>
-            Recommended polling time in minutes for short self-test.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-extended-self-test-polling-minutes" type="u" access="read">
-      <doc:doc><doc:description><doc:para>
-            Recommended polling time in minutes for extended self-test.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-conveyance-self-test-polling-minutes" type="u" access="read">
-      <doc:doc><doc:description><doc:para>
-            Recommended polling time in minutes for conveyance self-test.
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-ata-smart-time-collected">drive-ata-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
-    <property name="drive-ata-smart-attributes" type="a(usubbybybybbbutay)" access="read">
-      <doc:doc><doc:description><doc:para>
-            An array of ATA SMART attributes. Each element contains the following members (TODO).
-            This property is only valid if
-            <doc:ref type="property" to="Device:drive-smart-time-collected">drive-smart-time-collected</doc:ref>
-            is greater than zero.
-      </doc:para></doc:description></doc:doc>
-    </property>
 
     <!-- **************************************************************************************************** -->
 
index 42f21fe..2d9a0c2 100644 (file)
@@ -47,7 +47,6 @@ devkit_disks_daemon_SOURCES =                                                 \
        devkit-disks-mount.h            devkit-disks-mount.c            \
        devkit-disks-mount-monitor.h    devkit-disks-mount-monitor.c    \
        devkit-disks-inhibitor.h        devkit-disks-inhibitor.c        \
-       devkit-disks-ata-smart-db.h     devkit-disks-ata-smart-db.c     \
        devkit-disks-poller.h           devkit-disks-poller.c           \
        main.c                                                          \
        $(BUILT_SOURCES)
@@ -60,8 +59,6 @@ devkit_disks_daemon_CPPFLAGS =                                \
        $(NULL)
 
 devkit_disks_daemon_CFLAGS =                           \
-       $(ZLIB_CFLAGS)                                  \
-       $(SQLITE3_CFLAGS)                               \
        $(LIBATASMART_CFLAGS)                           \
        $(NULL)
 
@@ -70,8 +67,6 @@ devkit_disks_daemon_LDADD =                           \
        $(DBUS_GLIB_LIBS)                               \
        $(POLKIT_GOBJECT_1_LIBS)                        \
        $(GUDEV_LIBS)                                   \
-       $(ZLIB_LIBS)                                    \
-       $(SQLITE3_LIBS)                                 \
        $(LIBATASMART_LIBS)                             \
        $(NULL)
 
diff --git a/src/devkit-disks-ata-smart-db.c b/src/devkit-disks-ata-smart-db.c
deleted file mode 100644 (file)
index 2f247c0..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n-lib.h>
-#include <glib-object.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <sqlite3.h>
-#include <zlib.h>
-
-#include "devkit-disks-daemon.h"
-#include "devkit-disks-device.h"
-#include "devkit-disks-device-private.h"
-#include "devkit-disks-ata-smart-db.h"
-
-struct DevkitDisksAtaSmartDbPrivate
-{
-        sqlite3 *db;
-};
-
-G_DEFINE_TYPE (DevkitDisksAtaSmartDb, devkit_disks_ata_smart_db, G_TYPE_OBJECT)
-
-#define DEVKIT_DISKS_ATA_SMART_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVKIT_DISKS_TYPE_DEVICE, DevkitDisksDevicePrivate))
-
-
-static void
-devkit_disks_ata_smart_db_finalize (GObject *object)
-{
-        DevkitDisksAtaSmartDb *db = DEVKIT_DISKS_ATA_SMART_DB (object);
-
-        if (db->priv->db != NULL)
-                sqlite3_close (db->priv->db);
-
-        if (G_OBJECT_CLASS (devkit_disks_ata_smart_db_parent_class)->finalize != NULL)
-                G_OBJECT_CLASS (devkit_disks_ata_smart_db_parent_class)->finalize (object);
-}
-
-static void
-devkit_disks_ata_smart_db_class_init (DevkitDisksAtaSmartDbClass *klass)
-{
-        GObjectClass *object_class = (GObjectClass *) klass;
-
-        g_type_class_add_private (klass, sizeof (DevkitDisksAtaSmartDbPrivate));
-
-        object_class->finalize = devkit_disks_ata_smart_db_finalize;
-}
-
-static void
-devkit_disks_ata_smart_db_init (DevkitDisksAtaSmartDb *db)
-{
-        gint ret;
-        gchar *err_msg;
-
-        db->priv = G_TYPE_INSTANCE_GET_PRIVATE (db, DEVKIT_DISKS_TYPE_ATA_SMART_DB, DevkitDisksAtaSmartDbPrivate);
-
-        ret = sqlite3_open_v2 (PACKAGE_LOCALSTATE_DIR "/lib/DeviceKit-disks/ata-smart-db.sqlite3",
-                               &db->priv->db,
-                               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
-                               NULL);
-        if (ret != SQLITE_OK) {
-                g_debug ("error opening sqlite3 database at "
-                         PACKAGE_LOCALSTATE_DIR "/lib/DeviceKit-disks/ata-smart-db.sqlite3"
-                         ": %s", sqlite3_errmsg (db->priv->db));
-                sqlite3_close (db->priv->db);
-                g_object_unref (db);
-                goto out;
-        }
-
-        /* create tables */
-        ret = sqlite3_exec (db->priv->db,
-                            "CREATE TABLE AtaSmartEntry ("
-                            "  disk_id TEXT, "
-                            "  time_collected INTEGER, "
-                            "  is_failing INTEGER,"
-                            "  is_failing_valid INTEGER,"
-                            "  has_bad_sectors INTEGER,"
-                            "  has_bad_attributes INTEGER,"
-                            "  temperature_kelvin REAL,"
-                            "  power_on_secs INTEGER,"
-                            "  compressed_data BLOB "
-                            ");",
-                            NULL,
-                            NULL,
-                            &err_msg);
-        if (ret != SQLITE_OK) {
-                g_debug ("SQL error creating tables: %s", err_msg);
-                sqlite3_free (err_msg);
-        }
-
- out:
-        ;
-}
-
-DevkitDisksAtaSmartDb *
-devkit_disks_ata_smart_db_new (void)
-{
-        return DEVKIT_DISKS_ATA_SMART_DB (g_object_new (DEVKIT_DISKS_TYPE_ATA_SMART_DB, NULL));
-}
-
-static gchar *
-get_disk_id (DevkitDisksDevice *device)
-{
-        gchar *s;
-        gchar *result;
-
-        result = NULL;
-
-        if (device->priv->drive_vendor == NULL || strlen (device->priv->drive_vendor) == 0)
-                goto out;
-        if (device->priv->drive_model == NULL || strlen (device->priv->drive_model) == 0)
-                goto out;
-        if (device->priv->drive_revision == NULL || strlen (device->priv->drive_revision) == 0)
-                goto out;
-        if (device->priv->drive_serial == NULL || strlen (device->priv->drive_serial) == 0)
-                goto out;
-
-        s = g_strdup_printf ("%s_%s_%s_%s",
-                             device->priv->drive_vendor,
-                             device->priv->drive_model,
-                             device->priv->drive_revision,
-                             device->priv->drive_serial);
-        result = g_uri_escape_string (s, NULL, FALSE);
-        g_free (s);
-
-out:
-        return result;
-}
-
-void
-devkit_disks_ata_smart_db_add_entry (DevkitDisksAtaSmartDb *db,
-                                     DevkitDisksDevice     *device,
-                                     time_t                 time_collected,
-                                     gboolean               is_failing,
-                                     gboolean               is_failing_valid,
-                                     gboolean               has_bad_sectors,
-                                     gboolean               has_bad_attributes,
-                                     gdouble                temperature_kelvin,
-                                     guint64                power_on_seconds,
-                                     const void            *blob,
-                                     gsize                  blob_size)
-{
-        gint ret;
-        char *s;
-        gchar *disk_id;
-        sqlite3_stmt *stmt;
-        guchar *compressed_blob;
-        uLongf compressed_blob_size;
-
-        s = NULL;
-        stmt = NULL;
-        disk_id = NULL;
-        compressed_blob = NULL;
-
-        if (db->priv->db == NULL) {
-                g_warning ("No database");
-                goto out;
-        }
-
-        disk_id = get_disk_id (device);
-        if (disk_id == NULL) {
-                g_warning ("Error getting stable ID for device");
-                goto out;
-        }
-
-        /* compress the data */
-        compressed_blob = g_new0 (guchar, blob_size * 2 + 32);
-        compressed_blob_size = blob_size * 2 + 32;
-        ret = compress2 (compressed_blob, &compressed_blob_size,
-                         blob, blob_size,
-                         1);
-        if (ret != Z_OK) {
-                g_warning ("Error compressing blob (size=%d): %d", (gint) blob_size, ret);
-                goto out;
-        }
-
-        //g_debug ("Compressed %ld bytes into %ld bytes", blob_size, compressed_blob_size);
-
-        /* insert it into the database */
-        s = sqlite3_mprintf ("INSERT INTO AtaSmartEntry "
-                             "(disk_id, "
-                             "time_collected, "
-                             "is_failing, "
-                             "is_failing_valid, "
-                             "has_bad_sectors, "
-                             "has_bad_attributes, "
-                             "temperature_kelvin, "
-                             "power_on_secs, "
-                             "compressed_data) "
-                             "VALUES ('%q', "
-                             "%" G_GUINT64_FORMAT ", "
-                             "%d, "
-                             "%d, "
-                             "%d, "
-                             "%d, "
-                             "%g, "
-                             "%" G_GUINT64_FORMAT ", "
-                             "?)",
-                             disk_id,
-                             (guint64) time_collected,
-                             is_failing,
-                             is_failing_valid,
-                             has_bad_sectors,
-                             has_bad_attributes,
-                             temperature_kelvin,
-                             power_on_seconds);
-        ret = sqlite3_prepare_v2 (db->priv->db,
-                                  s,
-                                  -1,
-                                  &stmt,
-                                  NULL);
-        if (ret != SQLITE_OK) {
-                g_warning ("SQL error preparing statement: %d", ret);
-                goto out;
-        }
-        ret = sqlite3_bind_blob (stmt,
-                                 1,
-                                 compressed_blob,
-                                 compressed_blob_size,
-                                 SQLITE_STATIC);
-        if (ret != SQLITE_OK) {
-                g_warning ("SQL error binding BLOB: %d", ret);
-                goto out;
-        }
-        ret = sqlite3_step (stmt);
-        if (ret != SQLITE_DONE) {
-                g_warning ("SQL error executing statement: %d", ret);
-                goto out;
-        }
-
- out:
-        g_free (compressed_blob);
-        g_free (disk_id);
-        if (s != NULL)
-                sqlite3_free (s);
-        if (stmt != NULL)
-                sqlite3_finalize (stmt);
-}
-
-void
-devkit_disks_ata_smart_db_delete_entries (DevkitDisksAtaSmartDb *db,
-                                          time_t                 cut_off_point)
-{
-        char *s;
-        gint ret;
-        sqlite3_stmt *stmt;
-
-        s = NULL;
-        stmt = NULL;
-
-        s = sqlite3_mprintf ("DELETE FROM AtaSmartEntry WHERE time_collected < %"G_GUINT64_FORMAT ";",
-                             (guint64) cut_off_point);
-        ret = sqlite3_prepare_v2 (db->priv->db,
-                                  s,
-                                  -1,
-                                  &stmt,
-                                  NULL);
-        if (ret != SQLITE_OK) {
-                g_warning ("SQL error preparing statement: %d", ret);
-                goto out;
-        }
-        ret = sqlite3_step (stmt);
-        if (ret != SQLITE_DONE) {
-                g_warning ("SQL error executing statement: %d", ret);
-                goto out;
-        }
-
- out:
-        if (s != NULL)
-                sqlite3_free (s);
-        if (stmt != NULL)
-                sqlite3_finalize (stmt);
-}
-
-gboolean
-devkit_disks_ata_smart_db_get_entries (DevkitDisksAtaSmartDb              *db,
-                                       DevkitDisksDevice                  *device,
-                                       time_t                              since,
-                                       time_t                              until,
-                                       guint64                             spacing,
-                                       DevkitDisksAtaSmartDbGetEntriesFunc callback,
-                                       gpointer                            user_data)
-{
-        gboolean ret;
-        char *s;
-        sqlite3_stmt *stmt;
-        gchar *disk_id;
-        guint64 last_time_collected;
-
-        ret = FALSE;
-        stmt = NULL;
-
-        if (db->priv->db == NULL) {
-                g_warning ("No database");
-                goto out;
-        }
-
-        disk_id = get_disk_id (device);
-        if (disk_id == NULL) {
-                g_warning ("Error getting stable ID for device");
-                goto out;
-        }
-
-        s = sqlite3_mprintf ("SELECT"
-                             " AtaSmartEntry.time_collected,"
-                             " AtaSmartEntry.compressed_data, "
-                             " AtaSmartEntry.is_failing, "
-                             " AtaSmartEntry.is_failing_valid, "
-                             " AtaSmartEntry.has_bad_sectors, "
-                             " AtaSmartEntry.has_bad_attributes, "
-                             " AtaSmartEntry.temperature_kelvin, "
-                             " AtaSmartEntry.power_on_secs "
-                             "FROM AtaSmartEntry "
-                             "WHERE"
-                             " AtaSmartEntry.disk_id='%q' AND"
-                             " AtaSmartEntry.time_collected >= %" G_GUINT64_FORMAT " AND"
-                             " AtaSmartEntry.time_collected <= %" G_GUINT64_FORMAT " "
-                             "ORDER BY AtaSmartEntry.time_collected;",
-                             disk_id,
-                             since,
-                             until);
-        ret = sqlite3_prepare_v2 (db->priv->db,
-                                  s,
-                                  -1,
-                                  &stmt,
-                                  NULL);
-        if (ret != SQLITE_OK) {
-                g_warning ("SQL error preparing statement: %d", ret);
-                goto out;
-        }
-
-        last_time_collected = 0;
-        do {
-                guint64 time_collected;
-                const void *compressed_blob;
-                gsize compressed_blob_size;
-                static guchar blob[2048]; /* assume 2k is enough */
-                uLongf blob_size;
-                gint rc;
-                gboolean    is_failing;
-                gboolean    is_failing_valid;
-                gboolean    has_bad_sectors;
-                gboolean    has_bad_attributes;
-                gdouble     temperature_kelvin;
-                guint64     power_on_seconds;
-
-                ret = sqlite3_step (stmt);
-
-                if (ret == SQLITE_DONE)
-                        break;
-
-                if (ret != SQLITE_ROW) {
-                        g_warning ("SQL error stepping: %d", ret);
-                        goto out;
-                }
-
-                time_collected = sqlite3_column_int64 (stmt, 0);
-
-                if (time_collected < (guint64) since)
-                        continue;
-                if (time_collected > (guint64) until)
-                        continue;
-                if (time_collected - last_time_collected < spacing)
-                        continue;
-
-                last_time_collected = time_collected;
-
-
-                compressed_blob = sqlite3_column_blob (stmt, 1);
-                compressed_blob_size = sqlite3_column_bytes (stmt, 1);
-
-                is_failing = sqlite3_column_int (stmt, 2);
-                is_failing_valid = sqlite3_column_int (stmt, 3);
-                has_bad_sectors = sqlite3_column_int (stmt, 4);
-                has_bad_attributes = sqlite3_column_int (stmt, 5);
-                temperature_kelvin = sqlite3_column_double (stmt, 6);
-                power_on_seconds = sqlite3_column_int64 (stmt, 7);
-
-                blob_size = sizeof blob;
-                rc = uncompress (blob, &blob_size, compressed_blob, compressed_blob_size);
-                if (rc != Z_OK) {
-                        g_warning ("Decompression of compressed blob of size %d from time %" G_GUINT64_FORMAT
-                                   " for device %s FAILED with return code %d. Ignoring.",
-                                   (gint) compressed_blob_size,
-                                   time_collected,
-                                   device->priv->device_file,
-                                   rc);
-                        continue;
-                }
-
-                //g_debug ("haz row %ld %ld %ld", time_collected, compressed_blob_size, blob_size);
-
-                callback (time_collected,
-                          is_failing,
-                          is_failing_valid,
-                          has_bad_sectors,
-                          has_bad_attributes,
-                          temperature_kelvin,
-                          power_on_seconds,
-                          blob,
-                          blob_size,
-                          user_data);
-
-        } while (ret != SQLITE_DONE);
-
-
- out:
-        g_free (disk_id);
-        if (s != NULL)
-                sqlite3_free (s);
-        if (stmt != NULL)
-                sqlite3_finalize (stmt);
-        return ret;
-}
-
diff --git a/src/devkit-disks-ata-smart-db.h b/src/devkit-disks-ata-smart-db.h
deleted file mode 100644 (file)
index 100d0ee..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __DEVKIT_DISKS_ATA_SMART_DB_H__
-#define __DEVKIT_DISKS_ATA_SMART_DB_H__
-
-#include "devkit-disks-types.h"
-
-G_BEGIN_DECLS
-
-#define DEVKIT_DISKS_TYPE_ATA_SMART_DB         (devkit_disks_ata_smart_db_get_type ())
-#define DEVKIT_DISKS_ATA_SMART_DB(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVKIT_DISKS_TYPE_ATA_SMART_DB, DevkitDisksAtaSmartDb))
-#define DEVKIT_DISKS_ATA_SMART_DB_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), DEVKIT_DISKS_TYPE_ATA_SMART_DB, DevkitDisksAtaSmartDbClass))
-#define DEVKIT_DISKS_IS_ATA_SMART_DB(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVKIT_DISKS_TYPE_ATA_SMART_DB))
-#define DEVKIT_DISKS_IS_ATA_SMART_DB_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), DEVKIT_DISKS_TYPE_ATA_SMART_DB))
-#define DEVKIT_DISKS_ATA_SMART_DB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVKIT_DISKS_TYPE_ATA_SMART_DB, DevkitDisksAtaSmartDbClass))
-
-typedef struct DevkitDisksAtaSmartDbClass   DevkitDisksAtaSmartDbClass;
-typedef struct DevkitDisksAtaSmartDbPrivate DevkitDisksAtaSmartDbPrivate;
-
-struct DevkitDisksAtaSmartDb
-{
-        GObject                       parent;
-        DevkitDisksAtaSmartDbPrivate *priv;
-};
-
-struct DevkitDisksAtaSmartDbClass
-{
-        GObjectClass parent_class;
-};
-
-typedef gboolean (*DevkitDisksAtaSmartDbGetEntriesFunc) (time_t      time_collected,
-                                                         gboolean    is_failing,
-                                                         gboolean    is_failing_valid,
-                                                         gboolean    has_bad_sectors,
-                                                         gboolean    has_bad_attributes,
-                                                         gdouble     temperature_kelvin,
-                                                         guint64     power_on_seconds,
-                                                         const void *blob,
-                                                         gsize       blob_size,
-                                                         gpointer    user_data);
-
-GType                  devkit_disks_ata_smart_db_get_type       (void) G_GNUC_CONST;
-DevkitDisksAtaSmartDb *devkit_disks_ata_smart_db_new            (void);
-void                   devkit_disks_ata_smart_db_add_entry      (DevkitDisksAtaSmartDb              *db,
-                                                                 DevkitDisksDevice                  *device,
-                                                                 time_t                              time_collected,
-                                                                 gboolean                            is_failing,
-                                                                 gboolean                            is_failing_valid,
-                                                                 gboolean                            has_bad_sectors,
-                                                                 gboolean                            has_bad_attributes,
-                                                                 gdouble                             temperature_kelvin,
-                                                                 guint64                             power_on_seconds,
-                                                                 const void                         *blob,
-                                                                 gsize                               blob_size);
-void                   devkit_disks_ata_smart_db_delete_entries (DevkitDisksAtaSmartDb              *db,
-                                                                 time_t                              cut_off_point);
-gboolean               devkit_disks_ata_smart_db_get_entries    (DevkitDisksAtaSmartDb              *db,
-                                                                 DevkitDisksDevice                  *device,
-                                                                 time_t                              since,
-                                                                 time_t                              until,
-                                                                 guint64                             spacing,
-                                                                 DevkitDisksAtaSmartDbGetEntriesFunc callback,
-                                                                 gpointer                            user_data);
-
-G_END_DECLS
-
-#endif /* __DEVKIT_DISKS_ATA_SMART_DB_H__ */
index 9aa7ef4..b8c933b 100644 (file)
@@ -33,9 +33,6 @@
 /* clean up old ATA SMART entries every 24 hours (and on startup) */
 #define ATA_SMART_CLEANUP_INTERVAL_SECONDS (24*60*60)
 
-/* delete entries older than five days */
-#define ATA_SMART_KEEP_ENTRIES_SECONDS (5*24*60*60)
-
 /* ---------------------------------------------------------------------------------------------------- */
 
 #include <stdlib.h>
@@ -71,7 +68,6 @@
 #include "devkit-disks-mount-monitor.h"
 #include "devkit-disks-poller.h"
 #include "devkit-disks-inhibitor.h"
-#include "devkit-disks-ata-smart-db.h"
 
 #include "devkit-disks-daemon-glue.h"
 #include "devkit-disks-marshal.h"
@@ -117,8 +113,6 @@ struct DevkitDisksDaemonPrivate
 
         DevkitDisksMountMonitor *mount_monitor;
 
-        DevkitDisksAtaSmartDb   *ata_smart_db;
-
         guint                    ata_smart_refresh_timer_id;
         guint                    ata_smart_cleanup_timer_id;
 
@@ -338,12 +332,6 @@ static const DevkitDisksFilesystem known_file_systems[] = {
 
 static const int num_known_file_systems = sizeof (known_file_systems) / sizeof (DevkitDisksFilesystem);
 
-DevkitDisksAtaSmartDb *
-devkit_disks_daemon_local_get_ata_smart_db (DevkitDisksDaemon *daemon)
-{
-        return daemon->priv->ata_smart_db;
-}
-
 const DevkitDisksFilesystem *
 devkit_disks_daemon_local_get_fs_details (DevkitDisksDaemon  *daemon,
                                           const gchar        *filesystem_id)
@@ -587,10 +575,6 @@ devkit_disks_daemon_finalize (GObject *object)
                 g_object_unref (daemon->priv->mount_monitor);
         }
 
-        if (daemon->priv->ata_smart_db != NULL) {
-                g_object_unref (daemon->priv->ata_smart_db);
-        }
-
         if (daemon->priv->gudev_client != NULL) {
                 g_object_unref (daemon->priv->gudev_client);
         }
@@ -898,28 +882,6 @@ out:
 }
 
 static gboolean
-cleanup_ata_smart_data (DevkitDisksDaemon *daemon)
-{
-        time_t now;
-        time_t cut_off_point;
-
-        now = time (NULL);
-        cut_off_point = now - ATA_SMART_KEEP_ENTRIES_SECONDS;
-
-        g_print ("**** Deleting all ATA SMART data older than %d seconds\n", ATA_SMART_KEEP_ENTRIES_SECONDS);
-
-        devkit_disks_ata_smart_db_delete_entries (daemon->priv->ata_smart_db,
-                                                  cut_off_point);
-
-        /* cleanup in another N seconds */
-        daemon->priv->ata_smart_cleanup_timer_id = g_timeout_add_seconds (ATA_SMART_CLEANUP_INTERVAL_SECONDS,
-                                                                          (GSourceFunc) cleanup_ata_smart_data,
-                                                                          daemon);
-
-        return FALSE;
-}
-
-static gboolean
 refresh_ata_smart_data (DevkitDisksDaemon *daemon)
 {
         DevkitDisksDevice *device;
@@ -1027,8 +989,6 @@ register_disks_daemon (DevkitDisksDaemon *daemon)
         g_signal_connect (daemon->priv->mount_monitor, "mount-added", (GCallback) mount_added, daemon);
         g_signal_connect (daemon->priv->mount_monitor, "mount-removed", (GCallback) mount_removed, daemon);
 
-        daemon->priv->ata_smart_db = devkit_disks_ata_smart_db_new ();
-
         return TRUE;
 error:
         return FALSE;
@@ -1074,9 +1034,6 @@ devkit_disks_daemon_new (void)
         devkit_disks_mount_file_clean_stale (l);
         g_list_free (l);
 
-        /* clean up old ATA SMART data from the database */
-        cleanup_ata_smart_data (daemon);
-
         /* set up timer for refreshing ATA SMART data - we don't want to refresh immediately because
          * when adding a device we also do this...
          */
index f417079..dd0a4f0 100644 (file)
@@ -88,9 +88,6 @@ DevkitDisksDevice *devkit_disks_daemon_local_find_by_device_file (DevkitDisksDae
 DevkitDisksDevice *devkit_disks_daemon_local_find_by_dev         (DevkitDisksDaemon       *daemon,
                                                                   dev_t                    dev);
 
-DevkitDisksAtaSmartDb *devkit_disks_daemon_local_get_ata_smart_db (DevkitDisksDaemon       *daemon);
-
-
 typedef void (*DevkitDisksCheckAuthCallback) (DevkitDisksDaemon     *daemon,
                                               DevkitDisksDevice     *device,
                                               DBusGMethodInvocation *context,
index 6f4a063..6ab05e5 100644 (file)
@@ -1114,66 +1114,6 @@ devkit_disks_device_set_drive_ata_smart_is_available (DevkitDisksDevice *device,
 }
 
 void
-devkit_disks_device_set_drive_ata_smart_is_failing (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_is_failing != value))
-    {
-      device->priv->drive_ata_smart_is_failing = value;
-      emit_changed (device, "drive_ata_smart_is_failing");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_is_failing_valid (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_is_failing_valid != value))
-    {
-      device->priv->drive_ata_smart_is_failing_valid = value;
-      emit_changed (device, "drive_ata_smart_is_failing_valid");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_has_bad_sectors (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_has_bad_sectors != value))
-    {
-      device->priv->drive_ata_smart_has_bad_sectors = value;
-      emit_changed (device, "drive_ata_smart_has_bad_sectors");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_has_bad_attributes (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_has_bad_attributes != value))
-    {
-      device->priv->drive_ata_smart_has_bad_attributes = value;
-      emit_changed (device, "drive_ata_smart_has_bad_attributes");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_temperature_kelvin (DevkitDisksDevice *device, gdouble value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_temperature_kelvin != value))
-    {
-      device->priv->drive_ata_smart_temperature_kelvin = value;
-      emit_changed (device, "drive_ata_smart_temperature_kelvin");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_power_on_seconds (DevkitDisksDevice *device, guint64 value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_power_on_seconds != value))
-    {
-      device->priv->drive_ata_smart_power_on_seconds = value;
-      emit_changed (device, "drive_ata_smart_power_on_seconds");
-    }
-}
-
-void
 devkit_disks_device_set_drive_ata_smart_time_collected (DevkitDisksDevice *device, guint64 value)
 {
   if (G_UNLIKELY (device->priv->drive_ata_smart_time_collected != value))
@@ -1184,124 +1124,23 @@ devkit_disks_device_set_drive_ata_smart_time_collected (DevkitDisksDevice *devic
 }
 
 void
-devkit_disks_device_set_drive_ata_smart_offline_data_collection_status (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_offline_data_collection_status != value))
-    {
-      device->priv->drive_ata_smart_offline_data_collection_status = value;
-      emit_changed (device, "drive_ata_smart_offline_data_collection_status");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_offline_data_collection_seconds (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_offline_data_collection_seconds != value))
-    {
-      device->priv->drive_ata_smart_offline_data_collection_seconds = value;
-      emit_changed (device, "drive_ata_smart_offline_data_collection_seconds");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_self_test_execution_status (DevkitDisksDevice *device, guint value)
+devkit_disks_device_set_drive_ata_smart_status (DevkitDisksDevice *device, SkSmartOverall value)
 {
-  if (G_UNLIKELY (device->priv->drive_ata_smart_self_test_execution_status != value))
+  if (G_UNLIKELY (device->priv->drive_ata_smart_status != value))
     {
-      device->priv->drive_ata_smart_self_test_execution_status = value;
-      emit_changed (device, "drive_ata_smart_self_test_execution_status");
+      device->priv->drive_ata_smart_status = value;
+      emit_changed (device, "drive_ata_smart_status");
     }
 }
 
 void
-devkit_disks_device_set_drive_ata_smart_self_test_execution_percent_remaining (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_self_test_execution_percent_remaining != value))
-    {
-      device->priv->drive_ata_smart_self_test_execution_percent_remaining = value;
-      emit_changed (device, "drive_ata_smart_self_test_execution_percent_remaining");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_short_and_extended_self_test_available (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_short_and_extended_self_test_available != value))
-    {
-      device->priv->drive_ata_smart_short_and_extended_self_test_available = value;
-      emit_changed (device, "drive_ata_smart_short_and_extended_self_test_available");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_conveyance_self_test_available (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_conveyance_self_test_available != value))
-    {
-      device->priv->drive_ata_smart_conveyance_self_test_available = value;
-      emit_changed (device, "drive_ata_smart_conveyance_self_test_available");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_start_self_test_available (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_start_self_test_available != value))
-    {
-      device->priv->drive_ata_smart_start_self_test_available = value;
-      emit_changed (device, "drive_ata_smart_start_self_test_available");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_abort_self_test_available (DevkitDisksDevice *device, gboolean value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_abort_self_test_available != value))
-    {
-      device->priv->drive_ata_smart_abort_self_test_available = value;
-      emit_changed (device, "drive_ata_smart_abort_self_test_available");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_short_self_test_polling_minutes (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_short_self_test_polling_minutes != value))
-    {
-      device->priv->drive_ata_smart_short_self_test_polling_minutes = value;
-      emit_changed (device, "drive_ata_smart_short_self_test_polling_minutes");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_extended_self_test_polling_minutes (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_extended_self_test_polling_minutes != value))
-    {
-      device->priv->drive_ata_smart_extended_self_test_polling_minutes = value;
-      emit_changed (device, "drive_ata_smart_extended_self_test_polling_minutes");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_conveyance_self_test_polling_minutes (DevkitDisksDevice *device, guint value)
-{
-  if (G_UNLIKELY (device->priv->drive_ata_smart_conveyance_self_test_polling_minutes != value))
-    {
-      device->priv->drive_ata_smart_conveyance_self_test_polling_minutes = value;
-      emit_changed (device, "drive_ata_smart_conveyance_self_test_polling_minutes");
-    }
-}
-
-void
-devkit_disks_device_set_drive_ata_smart_attributes_steal (DevkitDisksDevice *device, GPtrArray *attributes)
+devkit_disks_device_set_drive_ata_smart_blob_steal (DevkitDisksDevice *device, gchar *blob, gsize blob_size)
 {
   /* TODO: compare? Not really needed, this happens very rarely */
 
-  g_ptr_array_foreach (device->priv->drive_ata_smart_attributes, (GFunc) g_value_array_free, NULL);
-  g_ptr_array_free (device->priv->drive_ata_smart_attributes, TRUE);
-
-  device->priv->drive_ata_smart_attributes = attributes;
+  g_free (device->priv->drive_ata_smart_blob);
+  device->priv->drive_ata_smart_blob = blob;
+  device->priv->drive_ata_smart_blob_size = blob_size;
 
-  emit_changed (device, "drive_ata_smart_attributes");
+  emit_changed (device, "drive_ata_smart_blob");
 }
index def26e7..038daf4 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <dbus/dbus-glib.h>
 #include <gudev/gudev.h>
+#include <atasmart.h>
 
 #include "devkit-disks-types.h"
 
@@ -31,30 +32,6 @@ G_BEGIN_DECLS
 struct Job;
 typedef struct Job Job;
 
-#define ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \
-                                                                      G_TYPE_UINT, \
-                                                                      G_TYPE_STRING, \
-                                                                      G_TYPE_UINT, \
-                                                                      G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \
-                                                                      G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                      G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                      G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                      G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \
-                                                                      G_TYPE_UINT, G_TYPE_UINT64, \
-                                                                      dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), \
-                                                                      G_TYPE_INVALID))
-
-#define ATA_SMART_HISTORICAL_SMART_DATA_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray",   \
-                                                                             G_TYPE_UINT64, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_DOUBLE, \
-                                                                             G_TYPE_UINT64, \
-                                                                             dbus_g_type_get_collection ("GPtrArray", ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE), \
-                                                                             G_TYPE_INVALID))
-
 #define LSOF_DATA_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray",   \
                                                        G_TYPE_UINT,     \
                                                        G_TYPE_UINT,     \
@@ -216,25 +193,10 @@ struct DevkitDisksDevicePrivate
         guint64 linux_md_sync_speed;
 
         gboolean drive_ata_smart_is_available;
-        gboolean drive_ata_smart_is_failing;
-        gboolean drive_ata_smart_is_failing_valid;
-        gboolean drive_ata_smart_has_bad_sectors;
-        gboolean drive_ata_smart_has_bad_attributes;
-        gdouble drive_ata_smart_temperature_kelvin;
-        guint64 drive_ata_smart_power_on_seconds;
         guint64 drive_ata_smart_time_collected;
-        guint drive_ata_smart_offline_data_collection_status;
-        guint drive_ata_smart_offline_data_collection_seconds;
-        guint drive_ata_smart_self_test_execution_status;
-        guint drive_ata_smart_self_test_execution_percent_remaining;
-        gboolean drive_ata_smart_short_and_extended_self_test_available;
-        gboolean drive_ata_smart_conveyance_self_test_available;
-        gboolean drive_ata_smart_start_self_test_available;
-        gboolean drive_ata_smart_abort_self_test_available;
-        guint drive_ata_smart_short_self_test_polling_minutes;
-        guint drive_ata_smart_extended_self_test_polling_minutes;
-        guint drive_ata_smart_conveyance_self_test_polling_minutes;
-        GPtrArray *drive_ata_smart_attributes;
+        SkSmartOverall drive_ata_smart_status;
+        void *drive_ata_smart_blob;
+        gsize drive_ata_smart_blob_size;
 
         /* the following properties are not (yet) exported */
         char *dm_name;
@@ -352,25 +314,9 @@ void devkit_disks_device_set_slaves_objpath (DevkitDisksDevice *device, GStrv va
 void devkit_disks_device_set_holders_objpath (DevkitDisksDevice *device, GStrv value);
 
 void devkit_disks_device_set_drive_ata_smart_is_available (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_is_failing (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_is_failing_valid (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_has_bad_sectors (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_has_bad_attributes (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_temperature_kelvin (DevkitDisksDevice *device, gdouble value);
-void devkit_disks_device_set_drive_ata_smart_power_on_seconds (DevkitDisksDevice *device, guint64 value);
 void devkit_disks_device_set_drive_ata_smart_time_collected (DevkitDisksDevice *device, guint64 value);
-void devkit_disks_device_set_drive_ata_smart_offline_data_collection_status (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_offline_data_collection_seconds (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_self_test_execution_status (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_self_test_execution_percent_remaining (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_short_and_extended_self_test_available (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_conveyance_self_test_available (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_start_self_test_available (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_abort_self_test_available (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_drive_ata_smart_short_self_test_polling_minutes (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_extended_self_test_polling_minutes (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_conveyance_self_test_polling_minutes (DevkitDisksDevice *device, guint value);
-void devkit_disks_device_set_drive_ata_smart_attributes_steal (DevkitDisksDevice *device, GPtrArray *attributes);
+void devkit_disks_device_set_drive_ata_smart_status (DevkitDisksDevice *device, SkSmartOverall value);
+void devkit_disks_device_set_drive_ata_smart_blob_steal (DevkitDisksDevice *device, gchar *blob, gsize blob_size);
 
 
 G_END_DECLS
index dac22e7..fbbfe18 100644 (file)
@@ -58,7 +58,6 @@
 #include "devkit-disks-mount-file.h"
 #include "devkit-disks-inhibitor.h"
 #include "devkit-disks-poller.h"
-#include "devkit-disks-ata-smart-db.h"
 
 /*--------------------------------------------------------------------------------------------------------------*/
 #include "devkit-disks-device-glue.h"
@@ -221,25 +220,9 @@ enum
         PROP_OPTICAL_DISC_NUM_SESSIONS,
 
         PROP_DRIVE_ATA_SMART_IS_AVAILABLE,
-        PROP_DRIVE_ATA_SMART_IS_FAILING,
-        PROP_DRIVE_ATA_SMART_IS_FAILING_VALID,
-        PROP_DRIVE_ATA_SMART_HAS_BAD_SECTORS,
-        PROP_DRIVE_ATA_SMART_HAS_BAD_ATTRIBUTES,
-        PROP_DRIVE_ATA_SMART_TEMPERATURE_KELVIN,
-        PROP_DRIVE_ATA_SMART_POWER_ON_SECONDS,
         PROP_DRIVE_ATA_SMART_TIME_COLLECTED,
-        PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_STATUS,
-        PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_SECONDS,
-        PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_STATUS,
-        PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_PERCENT_REMAINING,
-        PROP_DRIVE_ATA_SMART_SHORT_AND_EXTENDED_SELF_TEST_AVAILABLE,
-        PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_AVAILABLE,
-        PROP_DRIVE_ATA_SMART_START_SELF_TEST_AVAILABLE,
-        PROP_DRIVE_ATA_SMART_ABORT_SELF_TEST_AVAILABLE,
-        PROP_DRIVE_ATA_SMART_SHORT_SELF_TEST_POLLING_MINUTES,
-        PROP_DRIVE_ATA_SMART_EXTENDED_SELF_TEST_POLLING_MINUTES,
-        PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_POLLING_MINUTES,
-        PROP_DRIVE_ATA_SMART_ATTRIBUTES,
+        PROP_DRIVE_ATA_SMART_STATUS,
+        PROP_DRIVE_ATA_SMART_BLOB,
 
         PROP_LINUX_MD_COMPONENT_LEVEL,
         PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
@@ -550,62 +533,31 @@ get_property (GObject         *object,
        case PROP_DRIVE_ATA_SMART_IS_AVAILABLE:
                g_value_set_boolean (value, device->priv->drive_ata_smart_is_available);
                break;
-       case PROP_DRIVE_ATA_SMART_IS_FAILING:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_is_failing);
-               break;
-       case PROP_DRIVE_ATA_SMART_IS_FAILING_VALID:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_is_failing_valid);
-               break;
-       case PROP_DRIVE_ATA_SMART_HAS_BAD_SECTORS:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_has_bad_sectors);
-               break;
-       case PROP_DRIVE_ATA_SMART_HAS_BAD_ATTRIBUTES:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_has_bad_attributes);
-               break;
-       case PROP_DRIVE_ATA_SMART_TEMPERATURE_KELVIN:
-               g_value_set_double (value, device->priv->drive_ata_smart_temperature_kelvin);
-               break;
-       case PROP_DRIVE_ATA_SMART_POWER_ON_SECONDS:
-               g_value_set_uint64 (value, device->priv->drive_ata_smart_power_on_seconds);
-               break;
        case PROP_DRIVE_ATA_SMART_TIME_COLLECTED:
                g_value_set_uint64 (value, device->priv->drive_ata_smart_time_collected);
                break;
-       case PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_STATUS:
-               g_value_set_uint (value, device->priv->drive_ata_smart_offline_data_collection_status);
-               break;
-       case PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_SECONDS:
-               g_value_set_uint (value, device->priv->drive_ata_smart_offline_data_collection_seconds);
-               break;
-       case PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_STATUS:
-               g_value_set_uint (value, device->priv->drive_ata_smart_self_test_execution_status);
-               break;
-       case PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_PERCENT_REMAINING:
-               g_value_set_uint (value, device->priv->drive_ata_smart_self_test_execution_percent_remaining);
-               break;
-       case PROP_DRIVE_ATA_SMART_SHORT_AND_EXTENDED_SELF_TEST_AVAILABLE:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_short_and_extended_self_test_available);
-               break;
-       case PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_AVAILABLE:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_conveyance_self_test_available);
-               break;
-       case PROP_DRIVE_ATA_SMART_START_SELF_TEST_AVAILABLE:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_start_self_test_available);
-               break;
-       case PROP_DRIVE_ATA_SMART_ABORT_SELF_TEST_AVAILABLE:
-               g_value_set_boolean (value, device->priv->drive_ata_smart_abort_self_test_available);
-               break;
-       case PROP_DRIVE_ATA_SMART_SHORT_SELF_TEST_POLLING_MINUTES:
-               g_value_set_uint (value, device->priv->drive_ata_smart_short_self_test_polling_minutes);
-               break;
-       case PROP_DRIVE_ATA_SMART_EXTENDED_SELF_TEST_POLLING_MINUTES:
-               g_value_set_uint (value, device->priv->drive_ata_smart_extended_self_test_polling_minutes);
-               break;
-       case PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_POLLING_MINUTES:
-               g_value_set_uint (value, device->priv->drive_ata_smart_conveyance_self_test_polling_minutes);
+       case PROP_DRIVE_ATA_SMART_STATUS:
+                {
+                        const gchar *status;
+                        if (device->priv->drive_ata_smart_status == (SkSmartOverall) -1)
+                                status = "";
+                        else
+                                status = sk_smart_overall_to_string (device->priv->drive_ata_smart_status);
+                        g_value_set_string (value, status);
+                }
                break;
-       case PROP_DRIVE_ATA_SMART_ATTRIBUTES:
-               g_value_set_boxed (value, device->priv->drive_ata_smart_attributes);
+       case PROP_DRIVE_ATA_SMART_BLOB:
+                {
+                        GArray *a;
+                        a = g_array_new (FALSE, FALSE, 1);
+                        if (device->priv->drive_ata_smart_blob != NULL) {
+                                g_array_append_vals (a,
+                                                     device->priv->drive_ata_smart_blob,
+                                                     device->priv->drive_ata_smart_blob_size);
+                        }
+                        g_value_set_boxed (value, a);
+                        g_array_unref (a);
+                }
                break;
 
        case PROP_LINUX_MD_COMPONENT_LEVEL:
@@ -1041,81 +993,17 @@ devkit_disks_device_class_init (DevkitDisksDeviceClass *klass)
                 g_param_spec_boolean ("drive-ata-smart-is-available", NULL, NULL, FALSE, G_PARAM_READABLE));
         g_object_class_install_property (
                 object_class,
-                PROP_DRIVE_ATA_SMART_IS_FAILING,
-                g_param_spec_boolean ("drive-ata-smart-is-failing", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_IS_FAILING_VALID,
-                g_param_spec_boolean ("drive-ata-smart-is-failing-valid", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_HAS_BAD_SECTORS,
-                g_param_spec_boolean ("drive-ata-smart-has-bad-sectors", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_HAS_BAD_ATTRIBUTES,
-                g_param_spec_boolean ("drive-ata-smart-has-bad-attributes", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_TEMPERATURE_KELVIN,
-                g_param_spec_double ("drive-ata-smart-temperature-kelvin", NULL, NULL, 0, G_MAXDOUBLE, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_POWER_ON_SECONDS,
-                g_param_spec_uint64 ("drive-ata-smart-power-on-seconds", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
                 PROP_DRIVE_ATA_SMART_TIME_COLLECTED,
                 g_param_spec_uint64 ("drive-ata-smart-time-collected", NULL, NULL, 0, G_MAXUINT64, 0, G_PARAM_READABLE));
         g_object_class_install_property (
                 object_class,
-                PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_STATUS,
-                g_param_spec_uint ("drive-ata-smart-offline-data-collection-status", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_OFFLINE_DATA_COLLECTION_SECONDS,
-                g_param_spec_uint ("drive-ata-smart-offline-data-collection-seconds", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_STATUS,
-                g_param_spec_uint ("drive-ata-smart-self-test-execution-status", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_SELF_TEST_EXECUTION_PERCENT_REMAINING,
-                g_param_spec_uint ("drive-ata-smart-self-test-execution-percent-remaining", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_SHORT_AND_EXTENDED_SELF_TEST_AVAILABLE,
-                g_param_spec_boolean ("drive-ata-smart-short-and-extended-self-test-available", NULL, NULL, FALSE, G_PARAM_READABLE));
+                PROP_DRIVE_ATA_SMART_STATUS,
+                g_param_spec_string ("drive-ata-smart-status", NULL, NULL, NULL, G_PARAM_READABLE));
         g_object_class_install_property (
                 object_class,
-                PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_AVAILABLE,
-                g_param_spec_boolean ("drive-ata-smart-conveyance-self-test-available", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_START_SELF_TEST_AVAILABLE,
-                g_param_spec_boolean ("drive-ata-smart-start-self-test-available", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_ABORT_SELF_TEST_AVAILABLE,
-                g_param_spec_boolean ("drive-ata-smart-abort-self-test-available", NULL, NULL, FALSE, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_SHORT_SELF_TEST_POLLING_MINUTES,
-                g_param_spec_uint ("drive-ata-smart-short-self-test-polling-minutes", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_EXTENDED_SELF_TEST_POLLING_MINUTES,
-                g_param_spec_uint ("drive-ata-smart-extended-self-test-polling-minutes", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_CONVEYANCE_SELF_TEST_POLLING_MINUTES,
-                g_param_spec_uint ("drive-ata-smart-conveyance-self-test-polling-minutes", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READABLE));
-        g_object_class_install_property (
-                object_class,
-                PROP_DRIVE_ATA_SMART_ATTRIBUTES,
-                g_param_spec_boxed ("drive-ata-smart-attributes", NULL, NULL,
-                                    dbus_g_type_get_collection ("GPtrArray", ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE),
+                PROP_DRIVE_ATA_SMART_BLOB,
+                g_param_spec_boxed ("drive-ata-smart-blob", NULL, NULL,
+                                    dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR),
                                     G_PARAM_READABLE));
 
 
@@ -1221,7 +1109,7 @@ devkit_disks_device_init (DevkitDisksDevice *device)
         device->priv->slaves_objpath = g_ptr_array_new ();
         device->priv->holders_objpath = g_ptr_array_new ();
 
-        device->priv->drive_ata_smart_attributes = g_ptr_array_new ();
+        device->priv->drive_ata_smart_status = -1;
 }
 
 static void
@@ -1244,9 +1132,6 @@ devkit_disks_device_finalize (GObject *object)
 
         g_free (device->priv->native_path);
 
-        g_ptr_array_foreach (device->priv->drive_ata_smart_attributes, (GFunc) g_value_array_free, NULL);
-        g_ptr_array_free (device->priv->drive_ata_smart_attributes, TRUE);
-
         for (l = device->priv->polling_inhibitors; l != NULL; l = l->next) {
                 DevkitDisksInhibitor *inhibitor = DEVKIT_DISKS_INHIBITOR (l->data);
                 g_signal_handlers_disconnect_by_func (inhibitor, polling_inhibitor_disconnected_cb, device);
@@ -1324,6 +1209,8 @@ devkit_disks_device_finalize (GObject *object)
         g_ptr_array_foreach (device->priv->linux_md_slaves, (GFunc) g_free, NULL);
         g_ptr_array_free (device->priv->linux_md_slaves, TRUE);
 
+        g_free (device->priv->drive_ata_smart_blob);
+
         g_free (device->priv->dm_name);
         g_ptr_array_foreach (device->priv->slaves_objpath, (GFunc) g_free, NULL);
         g_ptr_array_free (device->priv->slaves_objpath, TRUE);
@@ -7770,76 +7657,6 @@ devkit_disks_device_filesystem_set_label (DevkitDisksDevice     *device,
 
 /*--------------------------------------------------------------------------------------------------------------*/
 
-typedef struct {
-        gboolean simulation;
-} DriveRefreshAtaSmartDataData;
-
-static DriveRefreshAtaSmartDataData *
-drive_ata_smart_refresh_data_data_new (gboolean simulation)
-{
-        DriveRefreshAtaSmartDataData *data;
-        data = g_new0 (DriveRefreshAtaSmartDataData, 1);
-        data->simulation = simulation;
-        return data;
-}
-
-static void
-drive_ata_smart_refresh_data_unref (DriveRefreshAtaSmartDataData *data)
-{
-        g_free (data);
-}
-
-typedef struct
-{
-        GPtrArray *attributes;
-        gboolean has_bad_attributes;
-
-} AtaSmartCollectAttrsData;
-
-static void
-ata_smart_collect_attrs (SkDisk *d, const SkSmartAttributeParsedData *a, void *user_data)
-{
-        AtaSmartCollectAttrsData *data = user_data;
-        GValue elem = {0};
-        GArray *raw_data;
-
-        raw_data = g_array_new (FALSE, TRUE, sizeof (guchar));
-        g_array_append_val (raw_data, a->raw[0]);
-        g_array_append_val (raw_data, a->raw[1]);
-        g_array_append_val (raw_data, a->raw[2]);
-        g_array_append_val (raw_data, a->raw[3]);
-        g_array_append_val (raw_data, a->raw[4]);
-        g_array_append_val (raw_data, a->raw[5]);
-
-        g_value_init (&elem, ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE);
-        g_value_take_boxed (&elem, dbus_g_type_specialized_construct (ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE));
-        dbus_g_type_struct_set (&elem,
-                                0, a->id,
-                                1, a->name,
-                                2, a->flags,
-                                3, a->online,
-                                4, a->prefailure,
-                                5, a->current_value,
-                                6, a->current_value_valid,
-                                7, a->worst_value,
-                                8, a->worst_value_valid,
-                                9, a->threshold,
-                                10, a->threshold_valid,
-                                11, a->good_now,
-                                12, a->good_now_valid,
-                                13, a->pretty_unit,
-                                14, a->pretty_value,
-                                15, raw_data,
-                                G_MAXUINT);
-
-        if (!a->good_now && a->good_now_valid && a->prefailure)
-                data->has_bad_attributes = TRUE;
-
-        g_ptr_array_add (data->attributes, g_value_get_boxed (&elem));
-
-        g_array_free (raw_data, TRUE);
-}
-
 /* may be called with context==NULL */
 static void
 drive_ata_smart_refresh_data_completed_cb (DBusGMethodInvocation *context,
@@ -7850,21 +7667,12 @@ drive_ata_smart_refresh_data_completed_cb (DBusGMethodInvocation *context,
                                            const char *stdout,
                                            gpointer user_data)
 {
-        DriveRefreshAtaSmartDataData *data = user_data;
         gint rc;
-        SkBool good;
-        uint64_t num_bad_sectors;
-        uint64_t temperature_mkelvin;
-        uint64_t power_on_mseconds;
-        const SkSmartParsedData *asd;
         SkDisk *d;
-        guchar *blob;
+        gchar *blob;
         gsize blob_size;
         time_t time_collected;
-        gboolean is_failing;
-        gboolean is_failing_valid;
-        AtaSmartCollectAttrsData collect_attrs_data;
-        DevkitDisksAtaSmartDb *db;
+        SkSmartOverall overall;
 
         d = NULL;
         blob = NULL;
@@ -7906,7 +7714,7 @@ drive_ata_smart_refresh_data_completed_cb (DBusGMethodInvocation *context,
                 goto out;
         }
 
-        blob = g_base64_decode (stdout, &blob_size);
+        blob = (gchar *) g_base64_decode (stdout, &blob_size);
 
         if (sk_disk_open (NULL, &d) != 0) {
                 if (context != NULL) {
@@ -7927,84 +7735,14 @@ drive_ata_smart_refresh_data_completed_cb (DBusGMethodInvocation *context,
                 goto out;
         }
 
-        if (sk_disk_smart_status (d, &good) != 0) {
-                is_failing = FALSE;
-                is_failing_valid = FALSE;
-        } else {
-                is_failing = !good;
-                is_failing_valid = TRUE;
-        }
-        devkit_disks_device_set_drive_ata_smart_is_failing (device, is_failing);
-        devkit_disks_device_set_drive_ata_smart_is_failing_valid (device, is_failing_valid);
-
-        if (sk_disk_smart_get_bad (d, &num_bad_sectors) != 0) {
-                num_bad_sectors = 0;
-        }
-        devkit_disks_device_set_drive_ata_smart_has_bad_sectors (device, (num_bad_sectors > 0));
-
         time_collected = time (NULL);
         devkit_disks_device_set_drive_ata_smart_time_collected (device, time_collected);
 
-        if (sk_disk_smart_get_temperature (d, &temperature_mkelvin) != 0) {
-                temperature_mkelvin = 0;
-        }
-        devkit_disks_device_set_drive_ata_smart_temperature_kelvin (device, temperature_mkelvin / 1000.0);
-
-        if (sk_disk_smart_get_power_on (d, &power_on_mseconds) != 0) {
-                power_on_mseconds = 0;
-        }
-        devkit_disks_device_set_drive_ata_smart_power_on_seconds (device, power_on_mseconds / 1000);
-
-        if (sk_disk_smart_parse (d, &asd) != 0) {
-                devkit_disks_device_set_drive_ata_smart_offline_data_collection_status (device, 0);
-                devkit_disks_device_set_drive_ata_smart_offline_data_collection_seconds (device, 0);
-                devkit_disks_device_set_drive_ata_smart_self_test_execution_status (device, 0);
-                devkit_disks_device_set_drive_ata_smart_self_test_execution_percent_remaining (device, 0);
-                devkit_disks_device_set_drive_ata_smart_short_and_extended_self_test_available (device, FALSE);
-                devkit_disks_device_set_drive_ata_smart_conveyance_self_test_available (device, FALSE);
-                devkit_disks_device_set_drive_ata_smart_start_self_test_available (device, FALSE);
-                devkit_disks_device_set_drive_ata_smart_abort_self_test_available (device, FALSE);
-                devkit_disks_device_set_drive_ata_smart_short_self_test_polling_minutes (device, 0);
-                devkit_disks_device_set_drive_ata_smart_extended_self_test_polling_minutes (device, 0);
-                devkit_disks_device_set_drive_ata_smart_conveyance_self_test_polling_minutes (device, 0);
-        } else {
-                devkit_disks_device_set_drive_ata_smart_offline_data_collection_status
-                        (device, asd->offline_data_collection_status);
-                devkit_disks_device_set_drive_ata_smart_offline_data_collection_seconds
-                        (device, asd->total_offline_data_collection_seconds);
-                devkit_disks_device_set_drive_ata_smart_self_test_execution_status
-                        (device, asd->self_test_execution_status);
-                devkit_disks_device_set_drive_ata_smart_self_test_execution_percent_remaining
-                        (device, asd->self_test_execution_percent_remaining);
-                devkit_disks_device_set_drive_ata_smart_short_and_extended_self_test_available
-                        (device, asd->short_and_extended_test_available);
-                devkit_disks_device_set_drive_ata_smart_conveyance_self_test_available
-                        (device, asd->conveyance_test_available);
-                devkit_disks_device_set_drive_ata_smart_start_self_test_available
-                        (device, asd->start_test_available);
-                devkit_disks_device_set_drive_ata_smart_abort_self_test_available
-                        (device, asd->abort_test_available);
-                devkit_disks_device_set_drive_ata_smart_short_self_test_polling_minutes
-                        (device, asd->short_test_polling_minutes);
-                devkit_disks_device_set_drive_ata_smart_extended_self_test_polling_minutes
-                        (device, asd->extended_test_polling_minutes);
-                devkit_disks_device_set_drive_ata_smart_conveyance_self_test_polling_minutes
-                        (device, asd->conveyance_test_polling_minutes);
-        }
-
-        collect_attrs_data.attributes = g_ptr_array_new ();
-        collect_attrs_data.has_bad_attributes = FALSE;
-        if (sk_disk_smart_parse_attributes (d, ata_smart_collect_attrs, &collect_attrs_data) != 0) {
-                if (context != NULL)
-                        throw_error (context,
-                                     DEVKIT_DISKS_ERROR_FAILED,
-                                     "Error parsing ATA SMART attributes: %m");
-                g_ptr_array_free (collect_attrs_data.attributes, TRUE);
-                goto out;
-        }
-
-        devkit_disks_device_set_drive_ata_smart_has_bad_attributes (device, collect_attrs_data.has_bad_attributes);
-        devkit_disks_device_set_drive_ata_smart_attributes_steal (device, collect_attrs_data.attributes);
+        if (sk_disk_smart_get_overall (d, &overall) != 0)
+                overall = -1;
+        devkit_disks_device_set_drive_ata_smart_status (device, overall);
+        devkit_disks_device_set_drive_ata_smart_blob_steal (device, blob, blob_size);
+        blob = NULL;
 
         /* emit change event since we've updated the smart data */
         drain_pending_changes (device, FALSE);
@@ -8012,22 +7750,6 @@ drive_ata_smart_refresh_data_completed_cb (DBusGMethodInvocation *context,
         if (context != NULL)
                 dbus_g_method_return (context);
 
-        /* store the (time_collected, disk_id, blob) tupple in our database if not simulating */
-        if (!data->simulation) {
-                db = devkit_disks_daemon_local_get_ata_smart_db (device->priv->daemon);
-                devkit_disks_ata_smart_db_add_entry (db,
-                                                     device,
-                                                     time_collected,
-                                                     is_failing,
-                                                     is_failing_valid,
-                                                     (num_bad_sectors > 0),
-                                                     collect_attrs_data.has_bad_attributes,
-                                                     temperature_mkelvin / 1000.0,
-                                                     power_on_mseconds / 1000,
-                                                     blob,
-                                                     blob_size);
-        }
-
 out:
         g_free (blob);
         if (d != NULL)
@@ -8099,8 +7821,8 @@ devkit_disks_device_drive_ata_smart_refresh_data_authorized_cb (DevkitDisksDaemo
                       argv,
                       NULL,
                       drive_ata_smart_refresh_data_completed_cb,
-                      drive_ata_smart_refresh_data_data_new (simuldata != NULL),
-                      (GDestroyNotify) drive_ata_smart_refresh_data_unref)) {
+                      NULL,
+                      NULL)) {
                 goto out;
         }
 
@@ -8144,138 +7866,6 @@ devkit_disks_device_drive_ata_smart_refresh_data (DevkitDisksDevice     *device,
 
 /*--------------------------------------------------------------------------------------------------------------*/
 
-static gboolean
-ata_smart_historical_data_cb (time_t      time_collected,
-                              gboolean    is_failing,
-                              gboolean    is_failing_valid,
-                              gboolean    has_bad_sectors,
-                              gboolean    has_bad_attributes,
-                              gdouble     temperature_kelvin,
-                              guint64     power_on_seconds,
-                              const void *blob,
-                              gsize       blob_size,
-                              gpointer    user_data)
-{
-        GPtrArray *array = user_data;
-        GValue elem = {0};
-        SkDisk *d;
-        AtaSmartCollectAttrsData collect_attrs_data;
-
-        d = NULL;
-
-        if (sk_disk_open (NULL, &d) != 0) {
-                g_warning ("Unable to open a SkDisk");
-                goto out;
-        }
-
-        if (sk_disk_set_blob (d, blob, blob_size) != 0) {
-                g_warning ("Error parsing blob: %s", strerror (errno));
-                goto out;
-        }
-
-        collect_attrs_data.attributes = g_ptr_array_new ();
-        collect_attrs_data.has_bad_attributes = FALSE;
-        if (sk_disk_smart_parse_attributes (d, ata_smart_collect_attrs, &collect_attrs_data) != 0) {
-                g_warning ("Error parsing ATA SMART attributes: %m");
-        }
-
-        g_value_init (&elem, ATA_SMART_HISTORICAL_SMART_DATA_STRUCT_TYPE);
-        g_value_take_boxed (&elem, dbus_g_type_specialized_construct (ATA_SMART_HISTORICAL_SMART_DATA_STRUCT_TYPE));
-        dbus_g_type_struct_set (&elem,
-                                0, time_collected,
-                                1, is_failing,
-                                2, is_failing_valid,
-                                3, has_bad_sectors,
-                                4, has_bad_attributes,
-                                5, temperature_kelvin,
-                                6, power_on_seconds,
-                                7, collect_attrs_data.attributes,
-                                G_MAXUINT);
-
-        g_ptr_array_foreach (collect_attrs_data.attributes, (GFunc) g_value_array_free, NULL);
-        g_ptr_array_free (collect_attrs_data.attributes, TRUE);
-
-        g_ptr_array_add (array, g_value_get_boxed (&elem));
-
- out:
-        if (d != NULL)
-                sk_disk_free (d);
-        return FALSE;
-}
-
-static void
-devkit_disks_device_drive_ata_smart_get_historical_data_authorized_cb (DevkitDisksDaemon     *daemon,
-                                                                       DevkitDisksDevice     *device,
-                                                                       DBusGMethodInvocation *context,
-                                                                       const gchar           *action_id,
-                                                                       guint                  num_user_data,
-                                                                       gpointer              *user_data_elements)
-{
-        guint64                since   = *((guint64*) user_data_elements[0]);
-        guint64                until   = *((guint64*) user_data_elements[1]);
-        guint64                spacing = *((guint64*) user_data_elements[2]);
-        GPtrArray *array;
-        DevkitDisksAtaSmartDb *db;
-
-        db = devkit_disks_daemon_local_get_ata_smart_db (device->priv->daemon);
-
-        array = g_ptr_array_new ();
-
-        devkit_disks_ata_smart_db_get_entries (db,
-                                               device,
-                                               since,
-                                               until,
-                                               spacing,
-                                               ata_smart_historical_data_cb,
-                                               array);
-
-        dbus_g_method_return (context, array);
-
-        g_ptr_array_foreach (array, (GFunc) g_value_array_free, NULL);
-        g_ptr_array_free (array, TRUE);
-}
-
-gboolean
-devkit_disks_device_drive_ata_smart_get_historical_data (DevkitDisksDevice     *device,
-                                                         guint64                since,
-                                                         guint64                until,
-                                                         guint64                spacing,
-                                                         DBusGMethodInvocation *context)
-{
-        if (!device->priv->drive_ata_smart_is_available) {
-                throw_error (context,
-                             DEVKIT_DISKS_ERROR_FAILED,
-                             "Device does not support ATA SMART");
-                goto out;
-        }
-
-        if (until == 0)
-                until = time (NULL);
-
-        if (since > until) {
-                throw_error (context, DEVKIT_DISKS_ERROR_FAILED, "Malformed time range (since > until)");
-                goto out;
-        }
-
-        devkit_disks_daemon_local_check_auth (device->priv->daemon,
-                                              device,
-                                              "org.freedesktop.devicekit.disks.drive-ata-smart-retrieve-historical-data",
-                                              "DriveAtaSmartGetHistoricalData",
-                                              TRUE,
-                                              devkit_disks_device_drive_ata_smart_get_historical_data_authorized_cb,
-                                              context,
-                                              3,
-                                              g_memdup (&since, sizeof (guint64)), g_free,
-                                              g_memdup (&until, sizeof (guint64)), g_free,
-                                              g_memdup (&spacing, sizeof (guint64)), g_free);
-
- out:
-        return TRUE;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
 static void
 drive_ata_smart_initiate_selftest_completed_cb (DBusGMethodInvocation *context,
                                                 DevkitDisksDevice *device,
@@ -8322,6 +7912,20 @@ devkit_disks_device_drive_ata_smart_initiate_selftest_authorized_cb (DevkitDisks
         int n;
         char *argv[10];
         GError *error;
+        const gchar *job_name;
+
+        if (g_strcmp0 (test, "short") == 0) {
+                job_name = "DriveAtaSmartSelftestShort";
+        } else if (g_strcmp0 (test, "extended") == 0) {
+                job_name = "DriveAtaSmartSelftestExtended";
+        } else if (g_strcmp0 (test, "conveyance") == 0) {
+                job_name = "DriveAtaSmartSelftestConveyance";
+        } else {
+                throw_error (context,
+                             DEVKIT_DISKS_ERROR_FAILED,
+                             "Malformed test");
+                goto out;
+        }
 
         n = 0;
         argv[n++] = PACKAGE_LIBEXEC_DIR "/devkit-disks-helper-ata-smart-selftest";
@@ -8331,7 +7935,7 @@ devkit_disks_device_drive_ata_smart_initiate_selftest_authorized_cb (DevkitDisks
 
         error = NULL;
         if (!job_new (context,
-                      "DriveAtaSmartInitiateSelftest",
+                      job_name,
                       TRUE,
                       device,
                       argv,
index a14791f..9546a95 100644 (file)
@@ -1,5 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
+NULL =
+
 INCLUDES = \
        -I$(top_builddir)/src -I$(top_srcdir)/src \
        -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
@@ -43,7 +45,12 @@ devkit_disks_CPPFLAGS =                              \
        $(DISABLE_DEPRECATED)                           \
        $(AM_CPPFLAGS)
 
+devkit_disks_CFLAGS =                                  \
+       $(LIBATASMART_CFLAGS)                           \
+       $(NULL)
+
 devkit_disks_LDADD =                                   \
+       $(LIBATASMART_LIBS)                             \
        $(DBUS_GLIB_LIBS)                               \
        $(POLKIT_DBUS_LIBS)
 
index 08aad96..ad80a23 100644 (file)
@@ -43,6 +43,8 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
+#include <atasmart.h>
+
 #include "devkit-disks-daemon-glue.h"
 #include "devkit-disks-device-glue.h"
 #include "devkit-disks-marshal.h"
@@ -233,7 +235,7 @@ print_job (gboolean    job_in_progress,
            double      job_percentage)
 {
         if (job_in_progress) {
-                g_print ("  job underway:            %s", job_id);
+                g_print ("  job underway:                %s", job_id);
                 if (job_percentage >= 0)
                         g_print (", %3.0lf%% complete", job_percentage);
                 if (job_is_cancellable)
@@ -241,7 +243,7 @@ print_job (gboolean    job_in_progress,
                 g_print (", initiated by uid %d", job_initiated_by_uid);
                 g_print ("\n");
         } else {
-                g_print ("  job underway:            no\n");
+                g_print ("  job underway:                no\n");
         }
 }
 
@@ -271,30 +273,6 @@ device_removed_signal_handler (DBusGProxy *proxy, const char *object_path, gpoin
   g_print ("removed:   %s\n", object_path);
 }
 
-#define ATA_SMART_ATTRIBUTE_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \
-                                                                 G_TYPE_UINT, \
-                                                                 G_TYPE_STRING, \
-                                                                 G_TYPE_UINT, \
-                                                                 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \
-                                                                 G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                 G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                 G_TYPE_UCHAR, G_TYPE_BOOLEAN, \
-                                                                 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \
-                                                                 G_TYPE_UINT, G_TYPE_UINT64, \
-                                                                 dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), \
-                                                                 G_TYPE_INVALID))
-
-#define ATA_SMART_HISTORICAL_SMART_DATA_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray",   \
-                                                                             G_TYPE_UINT64, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_BOOLEAN, \
-                                                                             G_TYPE_DOUBLE, \
-                                                                             G_TYPE_UINT64, \
-                                                                             dbus_g_type_get_collection ("GPtrArray", ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE), \
-                                                                             G_TYPE_INVALID))
-
 #define LSOF_DATA_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray",   \
                                                        G_TYPE_UINT,     \
                                                        G_TYPE_UINT,     \
@@ -398,25 +376,10 @@ typedef struct
         guint optical_disc_num_sessions;
 
         gboolean drive_ata_smart_is_available;
-        gboolean drive_ata_smart_is_failing;
-        gboolean drive_ata_smart_is_failing_valid;
-        gboolean drive_ata_smart_has_bad_sectors;
-        gboolean drive_ata_smart_has_bad_attributes;
-        gdouble drive_ata_smart_temperature_kelvin;
-        guint64 drive_ata_smart_power_on_seconds;
         guint64 drive_ata_smart_time_collected;
-        guint drive_ata_smart_offline_data_collection_status;
-        guint drive_ata_smart_offline_data_collection_seconds;
-        guint drive_ata_smart_self_test_execution_status;
-        guint drive_ata_smart_self_test_execution_percent_remaining;
-        gboolean drive_ata_smart_short_and_extended_self_test_available;
-        gboolean drive_ata_smart_conveyance_self_test_available;
-        gboolean drive_ata_smart_start_self_test_available;
-        gboolean drive_ata_smart_abort_self_test_available;
-        guint drive_ata_smart_short_self_test_polling_minutes;
-        guint drive_ata_smart_extended_self_test_polling_minutes;
-        guint drive_ata_smart_conveyance_self_test_polling_minutes;
-        GValue drive_ata_smart_attributes;
+        gchar *drive_ata_smart_status;
+        gchar *drive_ata_smart_blob;
+        gsize drive_ata_smart_blob_size;
 
         char    *linux_md_component_level;
         int      linux_md_component_num_raid_devices;
@@ -608,44 +571,15 @@ collect_props (const char *key, const GValue *value, DeviceProperties *props)
 
         else if (strcmp (key, "drive-ata-smart-is-available") == 0)
                 props->drive_ata_smart_is_available = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-is-failing") == 0)
-                props->drive_ata_smart_is_failing = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-is-failing-valid") == 0)
-                props->drive_ata_smart_is_failing_valid = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-has-bad-sectors") == 0)
-                props->drive_ata_smart_has_bad_sectors = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-has-bad-attributes") == 0)
-                props->drive_ata_smart_has_bad_attributes = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-temperature-kelvin") == 0)
-                props->drive_ata_smart_temperature_kelvin = g_value_get_double (value);
-        else if (strcmp (key, "drive-ata-smart-power-on-seconds") == 0)
-                props->drive_ata_smart_power_on_seconds = g_value_get_uint64 (value);
         else if (strcmp (key, "drive-ata-smart-time-collected") == 0)
                 props->drive_ata_smart_time_collected = g_value_get_uint64 (value);
-        else if (strcmp (key, "drive-ata-smart-offline-data-collection-status") == 0)
-                props->drive_ata_smart_offline_data_collection_status = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-offline-data-collection-seconds") == 0)
-                props->drive_ata_smart_offline_data_collection_seconds = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-self-test-execution-status") == 0)
-                props->drive_ata_smart_self_test_execution_status = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-self-test-execution-percent-remaining") == 0)
-                props->drive_ata_smart_self_test_execution_percent_remaining = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-short-and-extended-self-test-available") == 0)
-                props->drive_ata_smart_short_and_extended_self_test_available = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-conveyance-self-test-available") == 0)
-                props->drive_ata_smart_conveyance_self_test_available = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-start-self-test-available") == 0)
-                props->drive_ata_smart_start_self_test_available = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-abort-self-test-available") == 0)
-                props->drive_ata_smart_abort_self_test_available = g_value_get_boolean (value);
-        else if (strcmp (key, "drive-ata-smart-short-self-test-polling-minutes") == 0)
-                props->drive_ata_smart_short_self_test_polling_minutes = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-extended-self-test-polling-minutes") == 0)
-                props->drive_ata_smart_extended_self_test_polling_minutes = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-conveyance-self-test-polling-minutes") == 0)
-                props->drive_ata_smart_conveyance_self_test_polling_minutes = g_value_get_uint (value);
-        else if (strcmp (key, "drive-ata-smart-attributes") == 0) {
-                g_value_copy (value, &(props->drive_ata_smart_attributes));
+        else if (strcmp (key, "drive-ata-smart-status") == 0)
+                props->drive_ata_smart_status = g_strdup (g_value_get_string (value));
+        else if (strcmp (key, "drive-ata-smart-blob") == 0) {
+                GArray *a = g_value_get_boxed (value);
+                g_free (props->drive_ata_smart_blob);
+                props->drive_ata_smart_blob = g_memdup (a->data, a->len);
+                props->drive_ata_smart_blob_size = a->len;
         }
 
         else if (strcmp (key, "linux-md-component-level") == 0)
@@ -738,7 +672,8 @@ device_properties_free (DeviceProperties *props)
         g_strfreev (props->drive_media_compatibility);
         g_free (props->drive_media);
 
-        g_value_unset (&(props->drive_ata_smart_attributes));
+        g_free (props->drive_ata_smart_status);
+        g_free (props->drive_ata_smart_blob);
 
         g_free (props->linux_md_component_level);
         g_free (props->linux_md_component_uuid);
@@ -770,8 +705,6 @@ device_properties_get (DBusGConnection *bus,
         const char *ifname = "org.freedesktop.DeviceKit.Disks.Device";
 
         props = g_new0 (DeviceProperties, 1);
-        g_value_init (&(props->drive_ata_smart_attributes),
-                      dbus_g_type_get_collection ("GPtrArray", ATA_SMART_ATTRIBUTE_STRUCT_TYPE));
 
        prop_proxy = dbus_g_proxy_new_for_name (bus,
                                                 "org.freedesktop.DeviceKit.Disks",
@@ -828,53 +761,69 @@ do_monitor (void)
         return FALSE;
 }
 
-static const gchar *
-print_available (gboolean available)
+static gboolean
+has_colors (void)
 {
-        if (available)
-                return "available";
-        else
-                return "not available";
-}
+        static gboolean ret = FALSE;
+        static gboolean checked = FALSE;
 
-static const gchar *
-get_ata_smart_offline_status (guint offline_status)
-{
-        const gchar *ret;
-
-        switch (offline_status) {
-        case 0: ret = "never collected"; break;
-        case 1: ret = "successful"; break;
-        case 2: ret = "in progress"; break;
-        case 3: ret = "suspended"; break;
-        case 4: ret = "aborted"; break;
-        case 5: ret = "fatal"; break;
-        default: ret = "unknown"; break;
+        if (checked)
+                return ret;
+
+        if (isatty (STDOUT_FILENO)) {
+                ret = TRUE;
         }
 
+        checked = TRUE;
+
         return ret;
 }
 
+static void
+begin_highlight (void)
+{
+        if (has_colors ())
+                g_print ("\x1B[1;31m");
+}
+
+static void
+end_highlight (void)
+{
+        if (has_colors ())
+                g_print ("\x1B[0m");
+}
+
 static const gchar *
-get_ata_smart_self_test_status (guint self_test_status)
+ata_smart_status_to_desc (const gchar *status,
+                          gboolean    *out_highlight)
 {
-        const gchar *ret;
-
-        switch (self_test_status) {
-        case 0: ret = "success or never"; break;
-        case 1: ret = "aborted"; break;
-        case 2: ret = "interrupted"; break;
-        case 3: ret = "fatal"; break;
-        case 4: ret = "error (unknown)"; break;
-        case 5: ret = "error (electrical)"; break;
-        case 6: ret = "error (servo)"; break;
-        case 7: ret = "error (read)"; break;
-        case 8: ret = "error (handling)"; break;
-        case 15: ret = "in progress"; break;
-        default: ret = "unknown"; break;
+        const gchar *desc;
+        gboolean highlight;
+
+        highlight = FALSE;
+        if (g_strcmp0 (status, "GOOD") == 0) {
+                desc = "Good";
+        } else if (g_strcmp0 (status, "BAD_ATTRIBUTE_IN_THE_PAST") == 0) {
+                desc = "Disk was used outside of design parameters in the past";
+        } else if (g_strcmp0 (status, "BAD_SECTOR") == 0) {
+                desc = "Disk has a few bad sectors";
+        } else if (g_strcmp0 (status, "BAD_ATTRIBUTE_NOW") == 0) {
+                desc = "Disk is being used outside of design parameters";
+                highlight = TRUE;
+        } else if (g_strcmp0 (status, "BAD_SECTOR_MANY") == 0) {
+                desc = "Disk reports many bad sectors";
+                highlight = TRUE;
+        } else if (g_strcmp0 (status, "BAD_STATUS") == 0) {
+                desc = "Disk failure is imminent";
+                highlight = TRUE;
+        } else {
+                desc = status;
         }
 
-        return ret;
+        if (out_highlight != NULL)
+                *out_highlight = highlight;
+
+        return desc;
 }
 
 static gchar *
@@ -884,30 +833,30 @@ get_ata_smart_unit (guint unit, guint64 pretty_value)
 
         switch (unit) {
         default:
-        case 0:
-        case 1:
+        case SK_SMART_ATTRIBUTE_UNIT_UNKNOWN:
+        case SK_SMART_ATTRIBUTE_UNIT_NONE:
                 ret = g_strdup_printf ("%" G_GUINT64_FORMAT, pretty_value);
                 break;
 
-        case 2:
+        case SK_SMART_ATTRIBUTE_UNIT_MSECONDS:
                 if (pretty_value > 1000 * 60 * 60 * 24) {
-                        ret = g_strdup_printf ("%.3g days", pretty_value / 1000.0 / 60.0 / 60.0 / 24.0);
+                        ret = g_strdup_printf ("%3.1f days", pretty_value / 1000.0 / 60.0 / 60.0 / 24.0);
                 } else if (pretty_value > 1000 * 60 * 60) {
-                        ret = g_strdup_printf ("%.3g hours", pretty_value / 1000.0 / 60.0 / 60.0);
+                        ret = g_strdup_printf ("%3.1f hours", pretty_value / 1000.0 / 60.0 / 60.0);
                 } else if (pretty_value > 1000 * 60) {
-                        ret = g_strdup_printf ("%.3g mins", pretty_value / 1000.0 / 60.0);
+                        ret = g_strdup_printf ("%3.1f mins", pretty_value / 1000.0 / 60.0);
                 } else if (pretty_value > 1000) {
-                        ret = g_strdup_printf ("%.3g secs", pretty_value / 1000.0);
+                        ret = g_strdup_printf ("%3.1f secs", pretty_value / 1000.0);
                 } else {
                         ret = g_strdup_printf ("%d msec", (gint) pretty_value);
                 }
                 break;
 
-        case 3:
+        case SK_SMART_ATTRIBUTE_UNIT_SECTORS:
                 ret = g_strdup_printf ("%" G_GUINT64_FORMAT " sectors", pretty_value);
                 break;
 
-        case 4:
+        case SK_SMART_ATTRIBUTE_UNIT_MKELVIN:
                 ret = g_strdup_printf ("%.3gC / %.3gF",
                                        pretty_value / 1000.0 - 273.15,
                                        (pretty_value / 1000.0 - 273.15) * 9.0 / 5.0 + 32.0);
@@ -917,43 +866,84 @@ get_ata_smart_unit (guint unit, guint64 pretty_value)
         return ret;
 }
 
-static gboolean
-has_colors (void)
+static void
+print_ata_smart_attr (SkDisk *d, const SkSmartAttributeParsedData *a, void *user_data)
 {
-        static gboolean ret = FALSE;
-        static gboolean checked = FALSE;
-
-        if (checked)
-                return ret;
-
-        if (isatty (STDOUT_FILENO)) {
-                ret = TRUE;
+        const gchar *assessment;
+        const gchar *type;
+        const gchar *updates;
+        gchar *current_str;
+        gchar *worst_str;
+        gchar *threshold_str;
+        gchar *pretty;
+
+        pretty = get_ata_smart_unit (a->pretty_unit, a->pretty_value);
+
+        if (!a->good_now_valid) {
+                assessment = "   n/a   ";
+        } else {
+                if (!a->good_now) {
+                        assessment = "  FAIL   ";
+                } else {
+                        if (a->good_in_the_past_valid && !a->good_in_the_past) {
+                                assessment = "FAIL_PAST";
+                        } else {
+                                assessment = "  good   ";
+                        }
+                }
         }
 
-        checked = TRUE;
+        if (a->online)
+                updates = "Online ";
+        else
+                updates = "Offline";
 
-        return ret;
-}
+        if (a->prefailure)
+                type = "Pre-fail";
+        else
+                type = "Old-age ";
 
-static void
-begin_highlight (void)
-{
-        if (has_colors ())
-                g_print ("\x1B[1;31m");
-}
+        if (a->current_value_valid)
+                current_str = g_strdup_printf ("%3d", a->current_value);
+        else
+                current_str = g_strdup ("n/a");
 
-static void
-end_highlight (void)
-{
-        if (has_colors ())
-                g_print ("\x1B[0m");
+        if (a->worst_value_valid)
+                worst_str = g_strdup_printf ("%3d", a->worst_value);
+        else
+                worst_str = g_strdup ("n/a");
+
+        if (a->threshold_valid)
+                threshold_str = g_strdup_printf ("%3d", a->threshold);
+        else
+                threshold_str = g_strdup ("n/a");
+
+        if (a->warn)
+                begin_highlight ();
+
+        g_print (" %-27s %s|%s|%s %s %-11s %s %s\n",
+                 a->name,
+                 current_str,
+                 worst_str,
+                 threshold_str,
+                 assessment,
+                 pretty,
+                 type,
+                 updates);
+
+        if (a->warn)
+                end_highlight ();
+
+        g_free (current_str);
+        g_free (worst_str);
+        g_free (threshold_str);
+        g_free (pretty);
 }
 
 static void
 do_show_info (const char *object_path)
 {
         guint n;
-        guint m;
         DeviceProperties *props;
         struct tm *time_tm;
         time_t time;
@@ -968,19 +958,19 @@ do_show_info (const char *object_path)
         strftime (time_buf, sizeof time_buf, "%c", time_tm);
 
         g_print ("Showing information for %s\n", object_path);
-        g_print ("  native-path:             %s\n", props->native_path);
-        g_print ("  device:                  %" G_GINT64_MODIFIER "d:%" G_GINT64_MODIFIER "d\n",
+        g_print ("  native-path:                 %s\n", props->native_path);
+        g_print ("  device:                      %" G_GINT64_MODIFIER "d:%" G_GINT64_MODIFIER "d\n",
                  props->device_major,
                  props->device_minor);
-        g_print ("  device-file:             %s\n", props->device_file);
+        g_print ("  device-file:                 %s\n", props->device_file);
         for (n = 0; props->device_file_by_id[n] != NULL; n++)
-                g_print ("    by-id:                 %s\n", (char *) props->device_file_by_id[n]);
+                g_print ("    by-id:                     %s\n", (char *) props->device_file_by_id[n]);
         for (n = 0; props->device_file_by_path[n] != NULL; n++)
-                g_print ("    by-path:               %s\n", (char *) props->device_file_by_path[n]);
-        g_print ("  detected at:             %s\n", time_buf);
-        g_print ("  system internal:         %d\n", props->device_is_system_internal);
-        g_print ("  removable:               %d\n", props->device_is_removable);
-        g_print ("  has media:               %d", props->device_is_media_available);
+                g_print ("    by-path:                   %s\n", (char *) props->device_file_by_path[n]);
+        g_print ("  detected at:                 %s\n", time_buf);
+        g_print ("  system internal:             %d\n", props->device_is_system_internal);
+        g_print ("  removable:                   %d\n", props->device_is_removable);
+        g_print ("  has media:                   %d", props->device_is_media_available);
         if (props->device_media_detection_time != 0) {
                 time = (time_t) props->device_media_detection_time;
                 time_tm = localtime (&time);
@@ -988,12 +978,12 @@ do_show_info (const char *object_path)
                 g_print (" (detected at %s)", time_buf);
         }
         g_print ("\n");
-        g_print ("    detects change:        %d\n", props->device_is_media_change_detected);
-        g_print ("    detection by polling:  %d\n", props->device_is_media_change_detection_polling);
-        g_print ("    detection inhibitable: %d\n", props->device_is_media_change_detection_inhibitable);
-        g_print ("    detection inhibited:   %d\n", props->device_is_media_change_detection_inhibited);
-        g_print ("  is read only:            %d\n", props->device_is_read_only);
-        g_print ("  is mounted:              %d\n", props->device_is_mounted);
+        g_print ("    detects change:            %d\n", props->device_is_media_change_detected);
+        g_print ("    detection by polling:      %d\n", props->device_is_media_change_detection_polling);
+        g_print ("    detection inhibitable:     %d\n", props->device_is_media_change_detection_inhibitable);
+        g_print ("    detection inhibited:       %d\n", props->device_is_media_change_detection_inhibited);
+        g_print ("  is read only:                %d\n", props->device_is_read_only);
+        g_print ("  is mounted:                  %d\n", props->device_is_mounted);
         g_print ("  mount paths:             ");
         for (n = 0; props->device_mount_paths != NULL && props->device_mount_paths[n] != NULL; n++) {
                 if (n != 0)
@@ -1001,35 +991,35 @@ do_show_info (const char *object_path)
                 g_print ("%s", props->device_mount_paths[n]);
         }
         g_print ("\n");
-        g_print ("  mounted by uid:          %d\n", props->device_mounted_by_uid);
-        g_print ("  presentation hide:       %d\n", props->device_presentation_hide);
-        g_print ("  presentation nopolicy:   %d\n", props->device_presentation_nopolicy);
-        g_print ("  presentation name:       %s\n", props->device_presentation_name);
-        g_print ("  presentation icon:       %s\n", props->device_presentation_icon_name);
-        g_print ("  size:                    %" G_GUINT64_FORMAT "\n", props->device_size);
-        g_print ("  block size:              %" G_GUINT64_FORMAT "\n", props->device_block_size);
+        g_print ("  mounted by uid:              %d\n", props->device_mounted_by_uid);
+        g_print ("  presentation hide:           %d\n", props->device_presentation_hide);
+        g_print ("  presentation nopolicy:       %d\n", props->device_presentation_nopolicy);
+        g_print ("  presentation name:           %s\n", props->device_presentation_name);
+        g_print ("  presentation icon:           %s\n", props->device_presentation_icon_name);
+        g_print ("  size:                        %" G_GUINT64_FORMAT "\n", props->device_size);
+        g_print ("  block size:                  %" G_GUINT64_FORMAT "\n", props->device_block_size);
 
         print_job (props->job_in_progress,
                    props->job_id,
                    props->job_initiated_by_uid,
                    props->job_is_cancellable,
                    props->job_percentage);
-        g_print ("  usage:                   %s\n", props->id_usage);
-        g_print ("  type:                    %s\n", props->id_type);
-        g_print ("  version:                 %s\n", props->id_version);
-        g_print ("  uuid:                    %s\n", props->id_uuid);
-        g_print ("  label:                   %s\n", props->id_label);
+        g_print ("  usage:                       %s\n", props->id_usage);
+        g_print ("  type:                        %s\n", props->id_type);
+        g_print ("  version:                     %s\n", props->id_version);
+        g_print ("  uuid:                        %s\n", props->id_uuid);
+        g_print ("  label:                       %s\n", props->id_label);
         if (props->device_is_linux_md_component) {
                 g_print ("  linux md component:\n");
-                g_print ("    RAID level:            %s\n", props->linux_md_component_level);
-                g_print ("    num comp:              %d\n", props->linux_md_component_num_raid_devices);
-                g_print ("    uuid:                  %s\n", props->linux_md_component_uuid);
-                g_print ("    home host:             %s\n", props->linux_md_component_home_host);
-                g_print ("    name:                  %s\n", props->linux_md_component_name);
-                g_print ("    version:               %s\n", props->linux_md_component_version);
-                g_print ("    holder:                %s\n",
+                g_print ("    RAID level:                %s\n", props->linux_md_component_level);
+                g_print ("    num comp:                  %d\n", props->linux_md_component_num_raid_devices);
+                g_print ("    uuid:                      %s\n", props->linux_md_component_uuid);
+                g_print ("    home host:                 %s\n", props->linux_md_component_home_host);
+                g_print ("    name:                      %s\n", props->linux_md_component_name);
+                g_print ("    version:                   %s\n", props->linux_md_component_version);
+                g_print ("    holder:                    %s\n",
                          g_strcmp0 (props->linux_md_component_holder, "/") == 0 ? "(none)" : props->linux_md_component_holder);
-                g_print ("    state:                 ");
+                g_print ("    state:                     ");
                 for (n = 0;
                      props->linux_md_component_state != NULL && props->linux_md_component_state[n] != NULL;
                      n++) {
@@ -1041,262 +1031,132 @@ do_show_info (const char *object_path)
         }
         if (props->device_is_linux_md) {
                 g_print ("  linux md:\n");
-                g_print ("    state:                 %s\n", props->linux_md_state);
-                g_print ("    RAID level:            %s\n", props->linux_md_level);
-                g_print ("    uuid:                  %s\n", props->linux_md_uuid);
-                g_print ("    home host:             %s\n", props->linux_md_home_host);
-                g_print ("    name:                  %s\n", props->linux_md_name);
-                g_print ("    num comp:              %d\n", props->linux_md_num_raid_devices);
-                g_print ("    version:               %s\n", props->linux_md_version);
-                g_print ("    degraded:              %d\n", props->linux_md_is_degraded);
-                g_print ("    sync action:           %s\n", props->linux_md_sync_action);
+                g_print ("    state:                     %s\n", props->linux_md_state);
+                g_print ("    RAID level:                %s\n", props->linux_md_level);
+                g_print ("    uuid:                      %s\n", props->linux_md_uuid);
+                g_print ("    home host:                 %s\n", props->linux_md_home_host);
+                g_print ("    name:                      %s\n", props->linux_md_name);
+                g_print ("    num comp:                  %d\n", props->linux_md_num_raid_devices);
+                g_print ("    version:                   %s\n", props->linux_md_version);
+                g_print ("    degraded:                  %d\n", props->linux_md_is_degraded);
+                g_print ("    sync action:               %s\n", props->linux_md_sync_action);
                 if (strcmp (props->linux_md_sync_action, "idle") != 0) {
-                        g_print ("      complete:            %3.01f%%\n", props->linux_md_sync_percentage);
-                        g_print ("      speed:               %" G_GINT64_FORMAT " bytes/sec\n", props->linux_md_sync_speed);
+                        g_print ("      complete:                %3.01f%%\n", props->linux_md_sync_percentage);
+                        g_print ("      speed:                   %" G_GINT64_FORMAT " bytes/sec\n", props->linux_md_sync_speed);
                 }
                 g_print ("    slaves:\n");
                 for (n = 0; props->linux_md_slaves[n] != NULL; n++)
-                        g_print ("                  %s\n", props->linux_md_slaves[n]);
+                        g_print ("                      %s\n", props->linux_md_slaves[n]);
         }
         if (props->device_is_luks) {
                 g_print ("  luks device:\n");
-                g_print ("    holder:                %s\n", props->luks_holder);
+                g_print ("    holder:                    %s\n", props->luks_holder);
         }
         if (props->device_is_luks_cleartext) {
                 g_print ("  cleartext luks device:\n");
-                g_print ("    backed by:             %s\n", props->luks_cleartext_slave);
-                g_print ("    unlocked by:           uid %d\n", props->luks_cleartext_unlocked_by_uid);
+                g_print ("    backed by:                 %s\n", props->luks_cleartext_slave);
+                g_print ("    unlocked by:               uid %d\n", props->luks_cleartext_unlocked_by_uid);
         }
         if (props->device_is_partition_table) {
                 g_print ("  partition table:\n");
-                g_print ("    scheme:                %s\n", props->partition_table_scheme);
-                g_print ("    count:                 %d\n", props->partition_table_count);
+                g_print ("    scheme:                    %s\n", props->partition_table_scheme);
+                g_print ("    count:                     %d\n", props->partition_table_count);
         }
         if (props->device_is_partition) {
                 g_print ("  partition:\n");
-                g_print ("    part of:               %s\n", props->partition_slave);
-                g_print ("    scheme:                %s\n", props->partition_scheme);
-                g_print ("    number:                %d\n", props->partition_number);
-                g_print ("    type:                  %s\n", props->partition_type);
+                g_print ("    part of:                   %s\n", props->partition_slave);
+                g_print ("    scheme:                    %s\n", props->partition_scheme);
+                g_print ("    number:                    %d\n", props->partition_number);
+                g_print ("    type:                      %s\n", props->partition_type);
                 g_print ("    flags:                ");
                 for (n = 0; props->partition_flags[n] != NULL; n++)
                         g_print (" %s", (char *) props->partition_flags[n]);
                 g_print ("\n");
-                g_print ("    offset:                %" G_GINT64_FORMAT "\n", props->partition_offset);
-                g_print ("    size:                  %" G_GINT64_FORMAT "\n", props->partition_size);
-                g_print ("    label:                 %s\n", props->partition_label);
-                g_print ("    uuid:                  %s\n", props->partition_uuid);
+                g_print ("    offset:                    %" G_GINT64_FORMAT "\n", props->partition_offset);
+                g_print ("    size:                      %" G_GINT64_FORMAT "\n", props->partition_size);
+                g_print ("    label:                     %s\n", props->partition_label);
+                g_print ("    uuid:                      %s\n", props->partition_uuid);
         }
         if (props->device_is_optical_disc) {
                 g_print ("  optical disc:\n");
-                g_print ("    blank:                 %d\n", props->optical_disc_is_blank);
-                g_print ("    appendable:            %d\n", props->optical_disc_is_appendable);
-                g_print ("    closed:                %d\n", props->optical_disc_is_closed);
-                g_print ("    num tracks:            %d\n", props->optical_disc_num_tracks);
-                g_print ("    num audio tracks:      %d\n", props->optical_disc_num_audio_tracks);
-                g_print ("    num sessions:          %d\n", props->optical_disc_num_sessions);
+                g_print ("    blank:                     %d\n", props->optical_disc_is_blank);
+                g_print ("    appendable:                %d\n", props->optical_disc_is_appendable);
+                g_print ("    closed:                    %d\n", props->optical_disc_is_closed);
+                g_print ("    num tracks:                %d\n", props->optical_disc_num_tracks);
+                g_print ("    num audio tracks:          %d\n", props->optical_disc_num_audio_tracks);
+                g_print ("    num sessions:              %d\n", props->optical_disc_num_sessions);
         }
         if (props->device_is_drive) {
                 g_print ("  drive:\n");
-                g_print ("    vendor:                %s\n", props->drive_vendor);
-                g_print ("    model:                 %s\n", props->drive_model);
-                g_print ("    revision:              %s\n", props->drive_revision);
-                g_print ("    serial:                %s\n", props->drive_serial);
-                g_print ("    detachable:            %d\n", props->drive_can_detach);
-                g_print ("    can spindown:          %d\n", props->drive_can_spindown);
-                g_print ("    rotational media:      %d\n", props->drive_is_rotational);
-                g_print ("    ejectable:             %d\n", props->drive_is_media_ejectable);
-                g_print ("    media:                 %s\n", props->drive_media);
-                g_print ("      compat:             ");
+                g_print ("    vendor:                    %s\n", props->drive_vendor);
+                g_print ("    model:                     %s\n", props->drive_model);
+                g_print ("    revision:                  %s\n", props->drive_revision);
+                g_print ("    serial:                    %s\n", props->drive_serial);
+                g_print ("    detachable:                %d\n", props->drive_can_detach);
+                g_print ("    can spindown:              %d\n", props->drive_can_spindown);
+                g_print ("    rotational media:          %d\n", props->drive_is_rotational);
+                g_print ("    ejectable:                 %d\n", props->drive_is_media_ejectable);
+                g_print ("    media:                     %s\n", props->drive_media);
+                g_print ("      compat:                 ");
                 for (n = 0; props->drive_media_compatibility[n] != NULL; n++)
                         g_print (" %s", (char *) props->drive_media_compatibility[n]);
                 g_print ("\n");
                 if (props->drive_connection_interface == NULL || strlen (props->drive_connection_interface) == 0)
-                        g_print ("    interface:     (unknown)\n");
+                        g_print ("    interface:                 (unknown)\n");
                 else
-                        g_print ("    interface:             %s\n", props->drive_connection_interface);
+                        g_print ("    interface:                 %s\n", props->drive_connection_interface);
                 if (props->drive_connection_speed == 0)
-                        g_print ("    if speed:              (unknown)\n");
+                        g_print ("    if speed:                  (unknown)\n");
                 else
-                        g_print ("    if speed:              %" G_GINT64_FORMAT " bits/s\n", props->drive_connection_speed);
+                        g_print ("    if speed:                  %" G_GINT64_FORMAT " bits/s\n", props->drive_connection_speed);
 
                 /* ------------------------------------------------------------------------------------------------- */
 
                 if (!props->drive_ata_smart_is_available) {
-                        g_print ("    ATA SMART:             not available\n");
+                        g_print ("    ATA SMART:                 not available\n");
                 } else if (props->drive_ata_smart_time_collected == 0) {
-                        g_print ("    ATA SMART:             Data not collected\n");
+                        g_print ("    ATA SMART:                 Data not collected\n");
                 } else {
-                        GPtrArray *p;
+                        SkDisk *d;
 
                         time = (time_t) props->drive_ata_smart_time_collected;
                         time_tm = localtime (&time);
                         strftime (time_buf, sizeof time_buf, "%c", time_tm);
 
 
-                        g_print ("    ATA SMART:             Updated at %s\n", time_buf);
-                        if (props->drive_ata_smart_is_failing_valid) {
-                                if (!props->drive_ata_smart_is_failing)
-                                        g_print ("      assessment:          PASSED\n");
-                                else {
-                                        g_print ("      assessment:          ");
-                                        begin_highlight ();
-                                        g_print ("FAILING");
-                                        end_highlight ();
-                                        g_print ("\n");
-                                }
-
-                        } else {
-                                g_print ("      assessment:          Unknown\n");
-                        }
-
-                        if (props->drive_ata_smart_has_bad_sectors) {
-                                begin_highlight ();
-                                g_print ("      bad sectors:         Yes\n");
-                                end_highlight ();
-                        } else {
-                                g_print ("      bad sectors:         None\n");
-                        }
-
-                        if (props->drive_ata_smart_has_bad_attributes) {
-                                begin_highlight ();
-                                g_print ("      attributes:          One ore more attributes exceed threshold\n");
-                                end_highlight ();
-                        } else {
-                                g_print ("      attributes:          Within threshold\n");
-                        }
+                        g_print ("    ATA SMART:                 Updated at %s\n", time_buf);
 
-                        if (props->drive_ata_smart_temperature_kelvin < 0.1) {
-                                g_print ("      temperature:         Unknown\n");
+                        if (props->drive_ata_smart_status == NULL || strlen (props->drive_ata_smart_status) == 0) {
+                                g_print ("      overall assessment:      UNKNOWN\n");
                         } else {
-                                gdouble celcius;
-                                gdouble fahrenheit;
-                                celcius = props->drive_ata_smart_temperature_kelvin - 273.15;
-                                fahrenheit = 9.0 * celcius / 5.0 + 32.0;
-                                g_print ("      temperature:         %.3g\302\260 C / %.3g\302\260 F\n", celcius, fahrenheit);
-                        }
-
-                        if (props->drive_ata_smart_power_on_seconds == 0) {
-                                g_print ("      power on hours:      Unknown\n");
-                                g_print ("      powered on:          Unknown\n");
-                        } else {
-                                gchar *power_on_text;
-                                guint val;
-
-                                val = props->drive_ata_smart_power_on_seconds;
-
-                                if (val > 60 * 60 * 24) {
-                                        power_on_text = g_strdup_printf ("%.3g days", val / 60.0 / 60.0 / 24.0);
-                                } else {
-                                        power_on_text = g_strdup_printf ("%.3g hours", val / 60.0 / 60.0);
-                                }
-
-                                g_print ("      powered on:          %s\n", power_on_text);
-                                g_free (power_on_text);
-                        }
-
-
-                        g_print ("      offline data:        %s (%d second(s) to complete)\n", get_ata_smart_offline_status (props->drive_ata_smart_offline_data_collection_status), props->drive_ata_smart_offline_data_collection_seconds);
-                        g_print ("      self-test status:    %s (%d%% remaining)\n", get_ata_smart_self_test_status (props->drive_ata_smart_self_test_execution_status), props->drive_ata_smart_self_test_execution_percent_remaining);
-                        g_print ("      ext./short test:     %s\n", print_available (props->drive_ata_smart_short_and_extended_self_test_available));
-                        g_print ("      conveyance test:     %s\n", print_available (props->drive_ata_smart_conveyance_self_test_available));
-                        g_print ("      start test:          %s\n", print_available (props->drive_ata_smart_start_self_test_available));
-                        g_print ("      abort test:          %s\n", print_available (props->drive_ata_smart_abort_self_test_available));
-                        g_print ("      short test:          %3d minute(s) recommended polling time\n", props->drive_ata_smart_short_self_test_polling_minutes);
-                        g_print ("      ext. test:           %3d minute(s) recommended polling time\n", props->drive_ata_smart_extended_self_test_polling_minutes);
-                        g_print ("      conveyance test:     %3d minute(s) recommended polling time\n", props->drive_ata_smart_conveyance_self_test_polling_minutes);
-                        g_print ("===============================================================================\n");
-                        g_print (" Attribute       Current/Worst/Threshold  Status   Value       Type     Updates\n");
-                        g_print ("===============================================================================\n");
-                        p = g_value_get_boxed (&(props->drive_ata_smart_attributes));
-                        for (m = 0; m < p->len; m++) {
-                                GValue elem = {0};
-                                guint id;
-                                gchar *name;
-                                guint flags;
-                                gboolean online, prefailure;
-                                guchar current;
-                                gboolean current_valid;
-                                guchar worst;
-                                gboolean worst_valid;
-                                guchar threshold;
-                                gboolean threshold_valid;
-                                gboolean good, good_valid;
-                                guint pretty_unit;
-                                guint64 pretty_value;
-                                gchar *pretty;
-                                const gchar *assessment;
-                                const gchar *type;
-                                const gchar *updates;
+                                const gchar *status_desc;
                                 gboolean do_highlight;
-                                GArray *raw_data;
-
-                                g_value_init (&elem, ATA_SMART_ATTRIBUTE_STRUCT_TYPE);
-                                g_value_set_static_boxed (&elem, p->pdata[m]);
-
-                                dbus_g_type_struct_get (&elem,
-                                                         0, &id,
-                                                         1, &name,
-                                                         2, &flags,
-                                                         3, &online,
-                                                         4, &prefailure,
-                                                         5, &current,
-                                                         6, &current_valid,
-                                                         7, &worst,
-                                                         8, &worst_valid,
-                                                         9, &threshold,
-                                                        10, &threshold_valid,
-                                                        11, &good,
-                                                        12, &good_valid,
-                                                        13, &pretty_unit,
-                                                        14, &pretty_value,
-                                                        15, &raw_data,
-                                                        G_MAXUINT);
-
-                                pretty = get_ata_smart_unit (pretty_unit, pretty_value);
-
-                                do_highlight = FALSE;
-                                if (!good_valid)
-                                        assessment = " n/a";
-                                else if (good)
-                                        assessment = "good";
-                                else {
-                                        assessment = "FAIL";
-                                        do_highlight = TRUE;
-                                }
-
-                                if (online)
-                                        updates = "Online ";
-                                else
-                                        updates = "Offline";
 
-                                if (prefailure)
-                                        type = "Prefail";
-                                else
-                                        type = "Old-age";
+                                status_desc = ata_smart_status_to_desc (props->drive_ata_smart_status, &do_highlight);
 
                                 if (do_highlight)
                                         begin_highlight ();
-
-                                g_print (" %-27s %3d/%3d/%3d   %s    %-11s %s  %s\n",
-                                         name,
-                                         current,
-                                         worst,
-                                         threshold,
-                                         assessment,
-                                         pretty,
-                                         type,
-                                         updates);
-
+                                g_print ("      overall assessment:      %s\n", status_desc);
                                 if (do_highlight)
                                         end_highlight ();
+                        }
 
+                        if (sk_disk_open (NULL, &d) == 0) {
+                                if (sk_disk_set_blob (d,
+                                                      props->drive_ata_smart_blob,
+                                                      props->drive_ata_smart_blob_size) == 0) {
+                                        g_print ("===============================================================================\n");
+                                        g_print (" Attribute       Current|Worst|Threshold  Status   Value       Type     Updates\n");
+                                        g_print ("===============================================================================\n");
+
+                                        sk_disk_smart_parse_attributes (d,
+                                                                        print_ata_smart_attr,
+                                                                        NULL);
+                                }
+                                sk_disk_free (d);
+                        }
 
-                                g_free (pretty);
 
-                                g_array_free (raw_data, TRUE);
-                                g_value_unset (&elem);
-                        }
                 }
 
                 /* ------------------------------------------------------------------------------------------------- */