diff --git a/Makefile.am b/Makefile.am
index 1ec1d3f5a..1274de006 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,8 +44,8 @@ if !WITH_NVME
DISTCHECK_CONFIGURE_FLAGS += --without-nvme
endif
-if !WITH_SMART
-DISTCHECK_CONFIGURE_FLAGS += --without-smart
+if !WITH_SMARTMONTOOLS
+DISTCHECK_CONFIGURE_FLAGS += --without-smartmontools
endif
if !WITH_SWAP
@@ -72,7 +72,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \
configure depcomp install-sh ltmain.sh missing py-compile compile ar-lib \
m4/*.m4
-LIBDIRS = src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/plugins/nvme/.libs:src/lib/.libs
+LIBDIRS = src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs:src/lib/.libs
GIDIR = src/lib
if WITH_PYTHON3
diff --git a/configure.ac b/configure.ac
index 8c6dddacc..209bef6b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,6 +22,7 @@ AC_CONFIG_FILES([Makefile src/Makefile \
src/plugins/Makefile \
src/plugins/fs/Makefile \
src/plugins/nvme/Makefile \
+ src/plugins/smart/Makefile \
src/utils/Makefile \
src/utils/blockdev-utils.pc \
src/lib/Makefile \
@@ -153,16 +154,21 @@ AS_IF([test "x$with_nvme" != "xno"],
[AC_DEFINE([WITH_BD_NVME], [], [Define if nvme is supported]) AC_SUBST([WITH_NVME], [1])],
[])
-AC_ARG_WITH([smart],
- AS_HELP_STRING([--with-smart], [support smart @<:@default=yes@:>@]),
+AC_ARG_WITH([smartmontools],
+ AS_HELP_STRING([--with-smartmontools], [support ATA/SCSI S.M.A.R.T. via smartmontools @<:@default=yes@:>@]),
[],
- [with_smart=yes])
+ [with_smartmontools=yes])
+
+AC_SUBST([WITH_SMARTMONTOOLS], [0])
+AM_CONDITIONAL(WITH_SMARTMONTOOLS, test "x$with_smartmontools" != "xno")
+AS_IF([test "x$with_smartmontools" != "xno"],
+ [AC_DEFINE([WITH_BD_SMART], [], [Define if smart is supported])
+ AC_SUBST([WITH_SMART], [1])
+ AC_SUBST([WITH_SMARTMONTOOLS], [1])],
+ [])
AC_SUBST([WITH_SMART], [0])
-AM_CONDITIONAL(WITH_SMART, test "x$with_smart" != "xno")
-AS_IF([test "x$with_smart" != "xno"],
- [AC_DEFINE([WITH_BD_SMART], [], [Define if smart is supported]) AC_SUBST([WITH_SMART], [1])],
- [])
+AM_CONDITIONAL(WITH_SMART, test "x$with_smartmontools" != "xno")
LIBBLOCKDEV_PLUGIN([BTRFS], [btrfs])
LIBBLOCKDEV_PLUGIN([CRYPTO], [crypto])
@@ -177,7 +183,7 @@ LIBBLOCKDEV_PLUGIN([PART], [part])
LIBBLOCKDEV_PLUGIN([FS], [fs])
LIBBLOCKDEV_PLUGIN([NVDIMM], [nvdimm])
LIBBLOCKDEV_PLUGIN([NVME], [nvme])
-LIBBLOCKDEV_PLUGIN([SMART], [smart])
+LIBBLOCKDEV_PLUGIN([SMART], [smartmontools])
dnl these packages/modules are always needed
LIBBLOCKDEV_PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.42.2])
@@ -318,7 +324,7 @@ echo "
NVMe plugin: ${with_nvme}
Part plugin: ${with_part}
S390 plugin: ${s390_info}
- S.M.A.R.T. plugin: ${with_smart}
+ Smartmontools plugin: ${with_smartmontools}
Swap plugin: ${with_swap}
GObject introspection: ${found_introspection}
diff --git a/data/conf.d/00-default.cfg b/data/conf.d/00-default.cfg
index 08f85ccac..fe6e56d3c 100644
--- a/data/conf.d/00-default.cfg
+++ b/data/conf.d/00-default.cfg
@@ -46,7 +46,7 @@ sonames=libbd_nvme.so.3
sonames=libbd_part.so.3
[smart]
-sonames=libbd_smart.so.3
+sonames=libbd_smartmontools.so.3
[swap]
sonames=libbd_swap.so.3
diff --git a/include/blockdev/Makefile.am b/include/blockdev/Makefile.am
index e6246748a..a26bf60e0 100644
--- a/include/blockdev/Makefile.am
+++ b/include/blockdev/Makefile.am
@@ -1,6 +1,7 @@
all-local:
for header in ${srcdir}/../../src/plugins/*.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/plugins/nvme/nvme.h; do ln -sf $${header} ./; done
+ for header in ${srcdir}/../../src/plugins/smart/smart.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/utils/*.h; do ln -sf $${header} ./; done
for header in ${srcdir}/../../src/lib/*.h; do ln -sf $${header} ./; done
mkdir -p fs;
diff --git a/src/lib/blockdev.c.in b/src/lib/blockdev.c.in
index 2d00036ec..9bebce0f6 100644
--- a/src/lib/blockdev.c.in
+++ b/src/lib/blockdev.c.in
@@ -63,7 +63,7 @@ static gchar * default_plugin_so[BD_PLUGIN_UNDEF] = {
"libbd_dm.so.@MAJOR_VER@", "libbd_mdraid.so.@MAJOR_VER@",
"libbd_s390.so.@MAJOR_VER@", "libbd_part.so.@MAJOR_VER@",
"libbd_fs.so.@MAJOR_VER@", "libbd_nvdimm.so.@MAJOR_VER@",
- "libbd_nvme.so.@MAJOR_VER@", "libbd_smart.so.@MAJOR_VER@",
+ "libbd_nvme.so.@MAJOR_VER@", "libbd_smartmontools.so.@MAJOR_VER@",
};
static BDPluginStatus plugins[BD_PLUGIN_UNDEF] = {
{{BD_PLUGIN_LVM, NULL}, NULL},
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 1c3c26a26..99ac08abe 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -8,6 +8,10 @@ if WITH_NVME
SUBDIRS += nvme
endif
+if WITH_SMART
+SUBDIRS += smart
+endif
+
lib_LTLIBRARIES =
if WITH_BTRFS
@@ -46,10 +50,6 @@ if WITH_NVDIMM
lib_LTLIBRARIES += libbd_nvdimm.la
endif
-if WITH_SMART
-lib_LTLIBRARIES += libbd_smart.la
-endif
-
if WITH_SWAP
lib_LTLIBRARIES += libbd_swap.la
endif
@@ -140,14 +140,6 @@ libbd_nvdimm_la_CPPFLAGS = -I${builddir}/../../include/
libbd_nvdimm_la_SOURCES = nvdimm.c nvdimm.h check_deps.c check_deps.h
endif
-if WITH_SMART
-libbd_smart_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(JSON_GLIB_CFLAGS) -Wall -Wextra -Werror
-libbd_smart_la_LIBADD = ${builddir}/../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(JSON_GLIB_LIBS)
-libbd_smart_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 3:0:0 -Wl,--no-undefined
-libbd_smart_la_CPPFLAGS = -I${builddir}/../../include/
-libbd_smart_la_SOURCES = smart.c smart.h check_deps.c check_deps.h
-endif
-
if WITH_SWAP
libbd_swap_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(BLKID_CFLAGS) $(UUID_CFLAGS) -Wall -Wextra -Werror
libbd_swap_la_LIBADD = ${builddir}/../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(BLKID_LIBS) $(UUID_LIBS)
@@ -208,10 +200,6 @@ if WITH_NVDIMM
libinclude_HEADERS += nvdimm.h
endif
-if WITH_SMART
-libinclude_HEADERS += smart.h
-endif
-
if WITH_SWAP
libinclude_HEADERS += swap.h
endif
diff --git a/src/plugins/smart/Makefile.am b/src/plugins/smart/Makefile.am
new file mode 100644
index 000000000..f432afdb5
--- /dev/null
+++ b/src/plugins/smart/Makefile.am
@@ -0,0 +1,29 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+lib_LTLIBRARIES =
+
+
+if WITH_SMART
+libincludedir = $(includedir)/blockdev
+libinclude_HEADERS = smart.h
+endif
+
+
+if WITH_SMARTMONTOOLS
+
+lib_LTLIBRARIES += libbd_smartmontools.la
+
+libbd_smartmontools_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(JSON_GLIB_CFLAGS) -Wall -Wextra -Werror
+libbd_smartmontools_la_LIBADD = ${builddir}/../../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(JSON_GLIB_LIBS)
+libbd_smartmontools_la_LDFLAGS = -L${srcdir}/../../utils/ -version-info 3:0:0 -Wl,--no-undefined -export-symbols-regex '^bd_.*'
+libbd_smartmontools_la_CPPFLAGS = -I${builddir}/../../../include/ -I${srcdir}/../ -I. -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"
+
+libbd_smartmontools_la_SOURCES = \
+ smart.h \
+ smart-private.h \
+ smart-common.c \
+ smartmontools.c \
+ ../check_deps.c \
+ ../check_deps.h
+
+endif
diff --git a/src/plugins/smart/smart-common.c b/src/plugins/smart/smart-common.c
new file mode 100644
index 000000000..f849cb962
--- /dev/null
+++ b/src/plugins/smart/smart-common.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014-2024 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ * Author: Tomas Bzatek
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "smart.h"
+#include "smart-private.h"
+
+
+/**
+ * bd_smart_error_quark: (skip)
+ */
+GQuark bd_smart_error_quark (void)
+{
+ return g_quark_from_static_string ("g-bd-smart-error-quark");
+}
+
+/**
+ * bd_smart_ata_attribute_free: (skip)
+ * @attr: (nullable): %BDSmartATAAttribute to free
+ *
+ * Frees @attr.
+ */
+void bd_smart_ata_attribute_free (BDSmartATAAttribute *attr) {
+ if (attr == NULL)
+ return;
+ g_free (attr->name);
+ g_free (attr->well_known_name);
+ g_free (attr->pretty_value_string);
+ g_free (attr);
+}
+
+/**
+ * bd_smart_ata_attribute_copy: (skip)
+ * @attr: (nullable): %BDSmartATAAttribute to copy
+ *
+ * Creates a new copy of @attr.
+ */
+BDSmartATAAttribute * bd_smart_ata_attribute_copy (BDSmartATAAttribute *attr) {
+ BDSmartATAAttribute *new_attr;
+
+ if (attr == NULL)
+ return NULL;
+
+ new_attr = g_new0 (BDSmartATAAttribute, 1);
+ memcpy (new_attr, attr, sizeof (BDSmartATAAttribute));
+ new_attr->name = g_strdup (attr->name);
+ new_attr->well_known_name = g_strdup (attr->well_known_name);
+ new_attr->pretty_value_string = g_strdup (attr->pretty_value_string);
+
+ return new_attr;
+}
+
+/**
+ * bd_smart_ata_free: (skip)
+ * @data: (nullable): %BDSmartATA to free
+ *
+ * Frees @data.
+ */
+void bd_smart_ata_free (BDSmartATA *data) {
+ BDSmartATAAttribute **attr;
+
+ if (data == NULL)
+ return;
+
+ for (attr = data->attributes; attr && *attr; attr++)
+ bd_smart_ata_attribute_free (*attr);
+ g_free (data->attributes);
+ g_free (data);
+}
+
+/**
+ * bd_smart_ata_copy: (skip)
+ * @data: (nullable): %BDSmartATA to copy
+ *
+ * Creates a new copy of @data.
+ */
+BDSmartATA * bd_smart_ata_copy (BDSmartATA *data) {
+ BDSmartATA *new_data;
+ BDSmartATAAttribute **attr;
+ GPtrArray *ptr_array;
+
+ if (data == NULL)
+ return NULL;
+
+ new_data = g_new0 (BDSmartATA, 1);
+ memcpy (new_data, data, sizeof (BDSmartATA));
+
+ ptr_array = g_ptr_array_new ();
+ for (attr = data->attributes; attr && *attr; attr++)
+ g_ptr_array_add (ptr_array, bd_smart_ata_attribute_copy (*attr));
+ g_ptr_array_add (ptr_array, NULL);
+ new_data->attributes = (BDSmartATAAttribute **) g_ptr_array_free (ptr_array, FALSE);
+
+ return new_data;
+}
+
+/**
+ * bd_smart_scsi_free: (skip)
+ * @data: (nullable): %BDSmartSCSI to free
+ *
+ * Frees @data.
+ */
+void bd_smart_scsi_free (BDSmartSCSI *data) {
+ if (data == NULL)
+ return;
+
+ g_free (data->scsi_ie_string);
+ g_free (data);
+}
+
+/**
+ * bd_smart_scsi_copy: (skip)
+ * @data: (nullable): %BDSmartSCSI to copy
+ *
+ * Creates a new copy of @data.
+ */
+BDSmartSCSI * bd_smart_scsi_copy (BDSmartSCSI *data) {
+ BDSmartSCSI *new_data;
+
+ if (data == NULL)
+ return NULL;
+
+ new_data = g_new0 (BDSmartSCSI, 1);
+ memcpy (new_data, data, sizeof (BDSmartSCSI));
+ new_data->scsi_ie_string = g_strdup (data->scsi_ie_string);
+
+ return new_data;
+}
diff --git a/src/plugins/smart/smart-private.h b/src/plugins/smart/smart-private.h
new file mode 100644
index 000000000..764c6d6e6
--- /dev/null
+++ b/src/plugins/smart/smart-private.h
@@ -0,0 +1,100 @@
+#include
+#include
+#include
+
+#include "smart.h"
+
+#ifndef BD_SMART_PRIVATE
+#define BD_SMART_PRIVATE
+
+/* TODO: move to a common libblockdev header */
+#ifdef __clang__
+#define ZERO_INIT {}
+#else
+#define ZERO_INIT {0}
+#endif
+
+/* "C" locale to get the locale-agnostic error messages */
+#define _C_LOCALE (locale_t) 0
+
+
+struct WellKnownAttrInfo {
+ const gchar *libatasmart_name;
+ BDSmartATAAttributeUnit unit;
+ const gchar *smartmontools_names[7]; /* NULL-terminated */
+};
+
+/* This table was stolen from libatasmart, including the comment below: */
+/* This data is stolen from smartmontools */
+static const struct WellKnownAttrInfo well_known_attrs[256] = {
+ [1] = { "raw-read-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Raw_Read_Error_Count", "Raw_Read_Error_Rate", NULL }},
+ [2] = { "throughput-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Throughput_Performance", NULL }},
+ [3] = { "spin-up-time", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Spin_Up_Time", NULL }},
+ [4] = { "start-stop-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Start_Stop_Count", NULL }},
+ [5] = { "reallocated-sector-count", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Reallocated_Block_Count", "Reallocated_Sector_Ct", NULL }},
+ [6] = { "read-channel-margin", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Read_Channel_Margin", NULL }},
+ [7] = { "seek-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Seek_Error_Rate", NULL }},
+ [8] = { "seek-time-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Seek_Time_Performance", NULL }},
+ [9] = { "power-on-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Power_On_Hours", "Power_On_Hours_and_Msec", NULL }},
+ [10] = { "spin-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Spin_Retry_Count", NULL }},
+ [11] = { "calibration-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Calibration_Retry_Count", NULL }},
+ [12] = { "power-cycle-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power_Cycle_Count", "Device_Power_Cycle_Cnt", NULL }},
+ [13] = { "read-soft-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Read_Soft_Error_Rate", NULL }},
+ [170] = { "available-reserved-space", BD_SMART_ATA_ATTRIBUTE_UNIT_PERCENT, { "Available_Reservd_Space", "Reserved_Block_Pct", NULL }},
+ [171] = { "program-fail-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Cnt", "Program_Fail_Count", "Program_Fail_Ct", NULL }},
+ [172] = { "erase-fail-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Cnt", "Erase_Fail_Ct", "Erase_Fail_Count", "Block_Erase_Failure", NULL }},
+ [175] = { "program-fail-count-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Count_Chip", NULL }},
+ [176] = { "erase-fail-count-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Count_Chip", NULL }},
+ [177] = { "wear-leveling-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Wear_Leveling_Count", NULL }},
+ [178] = { "used-reserved-blocks-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Used_Rsvd_Blk_Cnt_Chip", "Used_Rsrvd_Blk_Cnt_Wrst", NULL }},
+ [179] = { "used-reserved-blocks-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Used_Rsvd_Blk_Cnt_Tot", "Used_Rsrvd_Blk_Cnt_Tot", NULL }},
+ [180] = { "unused-reserved-blocks", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Unused_Rsvd_Blk_Cnt_Tot", NULL }},
+ [181] = { "program-fail-count-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Cnt_Total", NULL }},
+ [182] = { "erase-fail-count-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Count_Total", NULL }},
+ [183] = { "runtime-bad-block-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Runtime_Bad_Block", NULL }},
+ [184] = { "end-to-end-error", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "End-to-End_Error", "End-to-End_Error_Count", NULL }},
+ [187] = { "reported-uncorrect", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Reported_Uncorrect", "Reported_UE_Counts", NULL }},
+ [188] = { "command-timeout", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Command_Timeout", "Command_Timeouts", NULL }},
+ [189] = { "high-fly-writes", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "High_Fly_Writes", NULL }},
+ [190] = { "airflow-temperature-celsius", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Airflow_Temperature_Cel", "Case_Temperature", "Drive_Temperature", "Temperature_Case", "Drive_Temp_Warning", "Temperature_Celsius", NULL }},
+ [191] = { "g-sense-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "G-Sense_Error_Rate", NULL }},
+ [192] = { "power-off-retract-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power-Off_Retract_Count", "Power-off_Retract_Count", NULL }},
+ [193] = { "load-cycle-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Cycle_Count", NULL }},
+ [194] = { "temperature-celsius-2", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Temperature_Celsius", "Device_Temperature", "Drive_Temperature", "Temperature_Internal", NULL }},
+ [195] = { "hardware-ecc-recovered", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Hardware_ECC_Recovered", "Cumulativ_Corrected_ECC", "ECC_Error_Rate", NULL }},
+ [196] = { "reallocated-event-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Reallocated_Event_Count", NULL }},
+ [197] = { "current-pending-sector", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Current_Pending_Sector", "Pending_Sector_Count", NULL }},
+ [198] = { "offline-uncorrectable", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Offline_Uncorrectable", "Uncor_Read_Error_Ct", "Uncorrectable_Sector_Ct", NULL }},
+ [199] = { "udma-crc-error-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "CRC_Error_Count", "SATA_CRC_Error", "SATA_CRC_Error_Count", "UDMA_CRC_Error_Count", NULL }},
+ [200] = { "multi-zone-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Multi_Zone_Error_Rate", NULL }},
+ [201] = { "soft-read-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Soft_Read_Error_Rate", "Read_Error_Rate", "Uncorr_Soft_Read_Err_Rt", "Unc_Read_Error_Rate", "Unc_Soft_Read_Err_Rate", NULL }},
+ [202] = { "ta-increase-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Data_Address_Mark_Errs", NULL }},
+ [203] = { "run-out-cancel", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Run_Out_Cancel", NULL }},
+ [204] = { "shock-count-write-open", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Soft_ECC_Correction", "Soft_ECC_Correction_Rt", "Soft_ECC_Correct_Rate", NULL }},
+ [205] = { "shock-rate-write-open", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Thermal_Asperity_Rate", NULL }},
+ [206] = { "flying-height", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Flying_Height", NULL }},
+ [207] = { "spin-high-current", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Spin_High_Current", NULL }},
+ [208] = { "spin-buzz", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Spin_Buzz", NULL }},
+ [209] = { "offline-seek-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Offline_Seek_Performnce", NULL }},
+ [220] = { "disk-shift", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Disk_Shift", NULL }},
+ [221] = { "g-sense-error-rate-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "G-Sense_Error_Rate", NULL }},
+ [222] = { "loaded-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Loaded_Hours", NULL }},
+ [223] = { "load-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Retry_Count", NULL }},
+ [224] = { "load-friction", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Load_Friction", NULL }},
+ [225] = { "load-cycle-count-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Cycle_Count", NULL }},
+ [226] = { "load-in-time", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Load-in_Time", NULL }},
+ [227] = { "torq-amp-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Torq-amp_Count", NULL }},
+ [228] = { "power-off-retract-count-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power-Off_Retract_Count", "Power-off_Retract_Count", NULL }},
+ [230] = { "head-amplitude", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Head_Amplitude", NULL }},
+ [231] = { "temperature-celsius", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Temperature_Celsius", "Controller_Temperature", NULL }},
+ [232] = { "endurance-remaining", BD_SMART_ATA_ATTRIBUTE_UNIT_PERCENT, { "Spares_Remaining_Perc", "Perc_Avail_Resrvd_Space", NULL }},
+ [233] = { "power-on-seconds-2", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { /* TODO */ NULL }},
+ [234] = { "uncorrectable-ecc-count", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { /* TODO */ NULL }},
+ [235] = { "good-block-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Good/Sys_Block_Count", NULL }},
+ [240] = { "head-flying-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Head_Flying_Hours", NULL }},
+ [241] = { "total-lbas-written", BD_SMART_ATA_ATTRIBUTE_UNIT_MB, { /* TODO: implement size calculation logic */ NULL }},
+ [242] = { "total-lbas-read", BD_SMART_ATA_ATTRIBUTE_UNIT_MB, { /* TODO: implement size calculation logic */ NULL }},
+ [250] = { "read-error-retry-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Read_Error_Retry_Rate", "Read_Retry_Count", NULL }},
+};
+
+#endif /* BD_SMART_PRIVATE */
diff --git a/src/plugins/smart.h b/src/plugins/smart/smart.h
similarity index 100%
rename from src/plugins/smart.h
rename to src/plugins/smart/smart.h
diff --git a/src/plugins/smart.c b/src/plugins/smart/smartmontools.c
similarity index 81%
rename from src/plugins/smart.c
rename to src/plugins/smart/smartmontools.c
index 2d4436d86..59ccdb25d 100644
--- a/src/plugins/smart.c
+++ b/src/plugins/smart/smartmontools.c
@@ -28,7 +28,9 @@
#include
#include
+
#include "smart.h"
+#include "smart-private.h"
/**
* SECTION: smart
@@ -41,14 +43,6 @@
#define SMARTCTL_MIN_VERSION "7.0"
-/**
- * bd_smart_error_quark: (skip)
- */
-GQuark bd_smart_error_quark (void)
-{
- return g_quark_from_static_string ("g-bd-smart-error-quark");
-}
-
static volatile guint avail_deps = 0;
static GMutex deps_check_lock;
@@ -128,119 +122,6 @@ gboolean bd_smart_is_tech_avail (G_GNUC_UNUSED BDSmartTech tech, G_GNUC_UNUSED g
}
-/**
- * bd_smart_ata_attribute_free: (skip)
- * @attr: (nullable): %BDSmartATAAttribute to free
- *
- * Frees @attr.
- */
-void bd_smart_ata_attribute_free (BDSmartATAAttribute *attr) {
- if (attr == NULL)
- return;
- g_free (attr->name);
- g_free (attr->well_known_name);
- g_free (attr->pretty_value_string);
- g_free (attr);
-}
-
-/**
- * bd_smart_ata_attribute_copy: (skip)
- * @attr: (nullable): %BDSmartATAAttribute to copy
- *
- * Creates a new copy of @attr.
- */
-BDSmartATAAttribute * bd_smart_ata_attribute_copy (BDSmartATAAttribute *attr) {
- BDSmartATAAttribute *new_attr;
-
- if (attr == NULL)
- return NULL;
-
- new_attr = g_new0 (BDSmartATAAttribute, 1);
- memcpy (new_attr, attr, sizeof (BDSmartATAAttribute));
- new_attr->name = g_strdup (attr->name);
- new_attr->well_known_name = g_strdup (attr->well_known_name);
- new_attr->pretty_value_string = g_strdup (attr->pretty_value_string);
-
- return new_attr;
-}
-
-/**
- * bd_smart_ata_free: (skip)
- * @data: (nullable): %BDSmartATA to free
- *
- * Frees @data.
- */
-void bd_smart_ata_free (BDSmartATA *data) {
- BDSmartATAAttribute **attr;
-
- if (data == NULL)
- return;
-
- for (attr = data->attributes; attr && *attr; attr++)
- bd_smart_ata_attribute_free (*attr);
- g_free (data->attributes);
- g_free (data);
-}
-
-/**
- * bd_smart_ata_copy: (skip)
- * @data: (nullable): %BDSmartATA to copy
- *
- * Creates a new copy of @data.
- */
-BDSmartATA * bd_smart_ata_copy (BDSmartATA *data) {
- BDSmartATA *new_data;
- BDSmartATAAttribute **attr;
- GPtrArray *ptr_array;
-
- if (data == NULL)
- return NULL;
-
- new_data = g_new0 (BDSmartATA, 1);
- memcpy (new_data, data, sizeof (BDSmartATA));
-
- ptr_array = g_ptr_array_new ();
- for (attr = data->attributes; attr && *attr; attr++)
- g_ptr_array_add (ptr_array, bd_smart_ata_attribute_copy (*attr));
- g_ptr_array_add (ptr_array, NULL);
- new_data->attributes = (BDSmartATAAttribute **) g_ptr_array_free (ptr_array, FALSE);
-
- return new_data;
-}
-
-/**
- * bd_smart_scsi_free: (skip)
- * @data: (nullable): %BDSmartSCSI to free
- *
- * Frees @data.
- */
-void bd_smart_scsi_free (BDSmartSCSI *data) {
- if (data == NULL)
- return;
-
- g_free (data->scsi_ie_string);
- g_free (data);
-}
-
-/**
- * bd_smart_scsi_copy: (skip)
- * @data: (nullable): %BDSmartSCSI to copy
- *
- * Creates a new copy of @data.
- */
-BDSmartSCSI * bd_smart_scsi_copy (BDSmartSCSI *data) {
- BDSmartSCSI *new_data;
-
- if (data == NULL)
- return NULL;
-
- new_data = g_new0 (BDSmartSCSI, 1);
- memcpy (new_data, data, sizeof (BDSmartSCSI));
- new_data->scsi_ie_string = g_strdup (data->scsi_ie_string);
-
- return new_data;
-}
-
static const gchar * get_error_message_from_exit_code (gint exit_code) {
/*
@@ -258,86 +139,6 @@ static const gchar * get_error_message_from_exit_code (gint exit_code) {
return NULL;
}
-
-struct WellKnownAttrInfo {
- const gchar *libatasmart_name;
- BDSmartATAAttributeUnit unit;
- const gchar *smartmontools_names[7]; /* NULL-terminated */
-};
-
-/* This table was stolen from libatasmart, including the comment below: */
-/* This data is stolen from smartmontools */
-static const struct WellKnownAttrInfo well_known_attrs[256] = {
- [1] = { "raw-read-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Raw_Read_Error_Count", "Raw_Read_Error_Rate", NULL }},
- [2] = { "throughput-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Throughput_Performance", NULL }},
- [3] = { "spin-up-time", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Spin_Up_Time", NULL }},
- [4] = { "start-stop-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Start_Stop_Count", NULL }},
- [5] = { "reallocated-sector-count", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Reallocated_Block_Count", "Reallocated_Sector_Ct", NULL }},
- [6] = { "read-channel-margin", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Read_Channel_Margin", NULL }},
- [7] = { "seek-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Seek_Error_Rate", NULL }},
- [8] = { "seek-time-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Seek_Time_Performance", NULL }},
- [9] = { "power-on-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Power_On_Hours", "Power_On_Hours_and_Msec", NULL }},
- [10] = { "spin-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Spin_Retry_Count", NULL }},
- [11] = { "calibration-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Calibration_Retry_Count", NULL }},
- [12] = { "power-cycle-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power_Cycle_Count", "Device_Power_Cycle_Cnt", NULL }},
- [13] = { "read-soft-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Read_Soft_Error_Rate", NULL }},
- [170] = { "available-reserved-space", BD_SMART_ATA_ATTRIBUTE_UNIT_PERCENT, { "Available_Reservd_Space", "Reserved_Block_Pct", NULL }},
- [171] = { "program-fail-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Cnt", "Program_Fail_Count", "Program_Fail_Ct", NULL }},
- [172] = { "erase-fail-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Cnt", "Erase_Fail_Ct", "Erase_Fail_Count", "Block_Erase_Failure", NULL }},
- [175] = { "program-fail-count-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Count_Chip", NULL }},
- [176] = { "erase-fail-count-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Count_Chip", NULL }},
- [177] = { "wear-leveling-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Wear_Leveling_Count", NULL }},
- [178] = { "used-reserved-blocks-chip", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Used_Rsvd_Blk_Cnt_Chip", "Used_Rsrvd_Blk_Cnt_Wrst", NULL }},
- [179] = { "used-reserved-blocks-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Used_Rsvd_Blk_Cnt_Tot", "Used_Rsrvd_Blk_Cnt_Tot", NULL }},
- [180] = { "unused-reserved-blocks", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Unused_Rsvd_Blk_Cnt_Tot", NULL }},
- [181] = { "program-fail-count-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Program_Fail_Cnt_Total", NULL }},
- [182] = { "erase-fail-count-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Erase_Fail_Count_Total", NULL }},
- [183] = { "runtime-bad-block-total", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Runtime_Bad_Block", NULL }},
- [184] = { "end-to-end-error", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "End-to-End_Error", "End-to-End_Error_Count", NULL }},
- [187] = { "reported-uncorrect", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Reported_Uncorrect", "Reported_UE_Counts", NULL }},
- [188] = { "command-timeout", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Command_Timeout", "Command_Timeouts", NULL }},
- [189] = { "high-fly-writes", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "High_Fly_Writes", NULL }},
- [190] = { "airflow-temperature-celsius", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Airflow_Temperature_Cel", "Case_Temperature", "Drive_Temperature", "Temperature_Case", "Drive_Temp_Warning", "Temperature_Celsius", NULL }},
- [191] = { "g-sense-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "G-Sense_Error_Rate", NULL }},
- [192] = { "power-off-retract-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power-Off_Retract_Count", "Power-off_Retract_Count", NULL }},
- [193] = { "load-cycle-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Cycle_Count", NULL }},
- [194] = { "temperature-celsius-2", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Temperature_Celsius", "Device_Temperature", "Drive_Temperature", "Temperature_Internal", NULL }},
- [195] = { "hardware-ecc-recovered", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Hardware_ECC_Recovered", "Cumulativ_Corrected_ECC", "ECC_Error_Rate", NULL }},
- [196] = { "reallocated-event-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Reallocated_Event_Count", NULL }},
- [197] = { "current-pending-sector", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Current_Pending_Sector", "Pending_Sector_Count", NULL }},
- [198] = { "offline-uncorrectable", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { "Offline_Uncorrectable", "Uncor_Read_Error_Ct", "Uncorrectable_Sector_Ct", NULL }},
- [199] = { "udma-crc-error-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "CRC_Error_Count", "SATA_CRC_Error", "SATA_CRC_Error_Count", "UDMA_CRC_Error_Count", NULL }},
- [200] = { "multi-zone-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Multi_Zone_Error_Rate", NULL }},
- [201] = { "soft-read-error-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Soft_Read_Error_Rate", "Read_Error_Rate", "Uncorr_Soft_Read_Err_Rt", "Unc_Read_Error_Rate", "Unc_Soft_Read_Err_Rate", NULL }},
- [202] = { "ta-increase-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Data_Address_Mark_Errs", NULL }},
- [203] = { "run-out-cancel", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Run_Out_Cancel", NULL }},
- [204] = { "shock-count-write-open", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Soft_ECC_Correction", "Soft_ECC_Correction_Rt", "Soft_ECC_Correct_Rate", NULL }},
- [205] = { "shock-rate-write-open", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Thermal_Asperity_Rate", NULL }},
- [206] = { "flying-height", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Flying_Height", NULL }},
- [207] = { "spin-high-current", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Spin_High_Current", NULL }},
- [208] = { "spin-buzz", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Spin_Buzz", NULL }},
- [209] = { "offline-seek-performance", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Offline_Seek_Performnce", NULL }},
- [220] = { "disk-shift", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Disk_Shift", NULL }},
- [221] = { "g-sense-error-rate-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "G-Sense_Error_Rate", NULL }},
- [222] = { "loaded-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Loaded_Hours", NULL }},
- [223] = { "load-retry-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Retry_Count", NULL }},
- [224] = { "load-friction", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Load_Friction", NULL }},
- [225] = { "load-cycle-count-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Load_Cycle_Count", NULL }},
- [226] = { "load-in-time", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Load-in_Time", NULL }},
- [227] = { "torq-amp-count", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Torq-amp_Count", NULL }},
- [228] = { "power-off-retract-count-2", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Power-Off_Retract_Count", "Power-off_Retract_Count", NULL }},
- [230] = { "head-amplitude", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Head_Amplitude", NULL }},
- [231] = { "temperature-celsius", BD_SMART_ATA_ATTRIBUTE_UNIT_MKELVIN, { "Temperature_Celsius", "Controller_Temperature", NULL }},
- [232] = { "endurance-remaining", BD_SMART_ATA_ATTRIBUTE_UNIT_PERCENT, { "Spares_Remaining_Perc", "Perc_Avail_Resrvd_Space", NULL }},
- [233] = { "power-on-seconds-2", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { /* TODO */ NULL }},
- [234] = { "uncorrectable-ecc-count", BD_SMART_ATA_ATTRIBUTE_UNIT_SECTORS, { /* TODO */ NULL }},
- [235] = { "good-block-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_UNKNOWN, { "Good/Sys_Block_Count", NULL }},
- [240] = { "head-flying-hours", BD_SMART_ATA_ATTRIBUTE_UNIT_MSECONDS, { "Head_Flying_Hours", NULL }},
- [241] = { "total-lbas-written", BD_SMART_ATA_ATTRIBUTE_UNIT_MB, { /* TODO: implement size calculation logic */ NULL }},
- [242] = { "total-lbas-read", BD_SMART_ATA_ATTRIBUTE_UNIT_MB, { /* TODO: implement size calculation logic */ NULL }},
- [250] = { "read-error-retry-rate", BD_SMART_ATA_ATTRIBUTE_UNIT_NONE, { "Read_Error_Retry_Rate", "Read_Retry_Count", NULL }},
-};
-
static void
lookup_well_known_attr (BDSmartATAAttribute *a,
gchar **well_known_name,
diff --git a/tests/run_tests.py b/tests/run_tests.py
index dbceb2aff..b1e5c3987 100644
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -17,7 +17,7 @@
from utils import TestTags, get_version
-LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs:src/plugins/nvme/.libs'
+LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs:src/plugins/nvme/.libs:src/plugins/smart/.libs'
GIDIR = 'src/lib'
SKIP_CONFIG = 'skip.yml'
diff --git a/tests/smart_test.py b/tests/smart_test.py
index 0f9b81a65..d5ccd2669 100644
--- a/tests/smart_test.py
+++ b/tests/smart_test.py
@@ -15,7 +15,7 @@ class SMARTTest(unittest.TestCase):
@tag_test(TestTags.NOSTORAGE)
def test_plugin_version(self):
- self.assertEqual(BlockDev.get_plugin_soname(BlockDev.Plugin.SMART), "libbd_smart.so.3")
+ self.assertEqual(BlockDev.get_plugin_soname(BlockDev.Plugin.SMART), "libbd_smartmontools.so.3")
@classmethod
def setUpClass(cls):