summaryrefslogtreecommitdiffstats
path: root/src/hardware
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-12-02 14:35:17 +0100
committerPeter Schiffer <pschiffe@redhat.com>2013-12-03 12:47:48 +0100
commit40b19060ec09099bece7ec50665d2f6e81985a9f (patch)
treed7941db8114f68262c56a03bef7e747ae737eba7 /src/hardware
parent8e995d10dcf6741960c2ea7633fcd2b5cc252870 (diff)
downloadopenlmi-providers-40b19060ec09099bece7ec50665d2f6e81985a9f.tar.gz
openlmi-providers-40b19060ec09099bece7ec50665d2f6e81985a9f.tar.xz
openlmi-providers-40b19060ec09099bece7ec50665d2f6e81985a9f.zip
Hardware: Created DiskDrive provider
New provider: * LMI_DiskDriveProvider Also, added missing config init to disk providers.
Diffstat (limited to 'src/hardware')
-rw-r--r--src/hardware/CMakeLists.txt2
-rw-r--r--src/hardware/LMI_DiskDriveProvider.c459
-rw-r--r--src/hardware/LMI_DiskPhysicalPackageContainerProvider.c7
-rw-r--r--src/hardware/LMI_DiskPhysicalPackageProvider.c7
-rw-r--r--src/hardware/LMI_Hardware.h1
-rw-r--r--src/hardware/smartctl.c51
-rw-r--r--src/hardware/smartctl.h17
7 files changed, 530 insertions, 14 deletions
diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt
index 2d3512b..74a20d0 100644
--- a/src/hardware/CMakeLists.txt
+++ b/src/hardware/CMakeLists.txt
@@ -30,7 +30,7 @@ add_library(${LIBRARY_NAME} SHARED
pkg_check_modules(LIBPCI REQUIRED libpci)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMPI_INCLUDE_DIR} ${LIBPCI_INCLUDE_DIR})
-target_link_libraries(${LIBRARY_NAME} openlmicommon ${KONKRETCMPI_LIBRARIES} ${LIBPCI_LIBRARIES})
+target_link_libraries(${LIBRARY_NAME} m openlmicommon ${KONKRETCMPI_LIBRARIES} ${LIBPCI_LIBRARIES})
# Create registration file
cim_registration(${PROVIDER_NAME} ${LIBRARY_NAME} ${MOF} share/openlmi-providers)
diff --git a/src/hardware/LMI_DiskDriveProvider.c b/src/hardware/LMI_DiskDriveProvider.c
new file mode 100644
index 0000000..9bfe8df
--- /dev/null
+++ b/src/hardware/LMI_DiskDriveProvider.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include <unistd.h>
+#include <konkret/konkret.h>
+#include "LMI_DiskDrive.h"
+#include "LMI_Hardware.h"
+#include "globals.h"
+#include "smartctl.h"
+#include "lsblk.h"
+#include "sysfs.h"
+
+CMPIUint16 get_operational_status(const char *smart_status);
+CMPIUint16 get_hdd_form_factor(const unsigned short form_factor);
+
+static const CMPIBroker* _cb = NULL;
+
+static void LMI_DiskDriveInitialize(const CMPIContext *ctx)
+{
+ lmi_init(provider_name, _cb, ctx, provider_config_defaults);
+}
+
+static CMPIStatus LMI_DiskDriveCleanup(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_DiskDriveEnumInstanceNames(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ return KDefaultEnumerateInstanceNames(
+ _cb, mi, cc, cr, cop);
+}
+
+static CMPIStatus LMI_DiskDriveEnumInstances(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ LMI_DiskDrive lmi_hdd;
+ const char *ns = KNameSpace(cop);
+ unsigned i, hdds_nb = 0, rotational = 0;
+ char instance_id[INSTANCE_ID_LEN], *id, *name, path[PATH_MAX], *basename;
+ CMPIUint16 operational_status;
+ SmartctlHdd *smtcl_hdds = NULL;
+ unsigned smtcl_hdds_nb = 0;
+ LsblkHdd *lsblk_hdds = NULL;
+ unsigned lsblk_hdds_nb = 0;
+
+ if (smartctl_get_hdds(&smtcl_hdds, &smtcl_hdds_nb) != 0 || smtcl_hdds_nb < 1) {
+ smartctl_free_hdds(&smtcl_hdds, &smtcl_hdds_nb);
+ if (lsblk_get_hdds(&lsblk_hdds, &lsblk_hdds_nb) != 0 || lsblk_hdds_nb < 1) {
+ goto done;
+ }
+ }
+
+ if (smtcl_hdds_nb > 0) {
+ hdds_nb = smtcl_hdds_nb;
+ } else {
+ hdds_nb = lsblk_hdds_nb;
+ }
+
+ for (i = 0; i < hdds_nb; i++) {
+ /* in fallback mode, use only disk devices from lsblk */
+ if (smtcl_hdds_nb < 1) {
+ if (strcmp(lsblk_hdds[i].type, "disk") != 0) {
+ continue;
+ }
+ }
+
+ if (smtcl_hdds_nb > 0) {
+ id = smtcl_hdds[i].serial_number;
+ name = smtcl_hdds[i].name;
+ basename = smtcl_hdds[i].dev_basename;
+ } else {
+ id = lsblk_hdds[i].name;
+ name = lsblk_hdds[i].name;
+ basename = lsblk_hdds[i].basename;
+ }
+
+ LMI_DiskDrive_Init(&lmi_hdd, _cb, ns);
+
+ LMI_DiskDrive_Set_SystemCreationClassName(&lmi_hdd,
+ get_system_creation_class_name());
+ LMI_DiskDrive_Set_SystemName(&lmi_hdd, get_system_name());
+ LMI_DiskDrive_Set_CreationClassName(&lmi_hdd,
+ ORGID "_" DISK_DRIVE_CLASS_NAME);
+ LMI_DiskDrive_Set_Caption(&lmi_hdd, "Disk Drive");
+ LMI_DiskDrive_Set_Description(&lmi_hdd,
+ "This object represents one physical disk drive in system.");
+
+ snprintf(instance_id, INSTANCE_ID_LEN,
+ ORGID ":" ORGID "_" DISK_DRIVE_CLASS_NAME ":%s", id);
+
+ LMI_DiskDrive_Set_DeviceID(&lmi_hdd, id);
+ LMI_DiskDrive_Set_Name(&lmi_hdd, name);
+ LMI_DiskDrive_Set_ElementName(&lmi_hdd, name);
+ LMI_DiskDrive_Set_InstanceID(&lmi_hdd, instance_id);
+
+ /* if we have smartctl output */
+ if (smtcl_hdds_nb > 0) {
+ operational_status = get_operational_status(
+ smtcl_hdds[i].smart_status);
+
+ LMI_DiskDrive_Init_OperationalStatus(&lmi_hdd, 1);
+ LMI_DiskDrive_Set_OperationalStatus(&lmi_hdd, 0, operational_status);
+ if (operational_status == LMI_DiskDrive_OperationalStatus_OK) {
+ LMI_DiskDrive_Set_EnabledState(&lmi_hdd,
+ LMI_DiskDrive_EnabledState_Enabled);
+ } else {
+ LMI_DiskDrive_Set_EnabledState(&lmi_hdd,
+ LMI_DiskDrive_EnabledState_Unknown);
+ }
+
+ LMI_DiskDrive_Set_FormFactor(&lmi_hdd,
+ get_hdd_form_factor(smtcl_hdds[i].form_factor));
+ LMI_DiskDrive_Set_InterconnectSpeed(&lmi_hdd,
+ smtcl_hdds[i].port_speed);
+ LMI_DiskDrive_Set_RPM(&lmi_hdd, smtcl_hdds[i].rpm);
+ }
+
+ snprintf(path, PATH_MAX, SYSFS_BLOCK_PATH "/%s/queue/rotational",
+ basename);
+ if (path_get_unsigned(path, &rotational) == 0) {
+ if (rotational == 1) {
+ LMI_DiskDrive_Set_DiskType(&lmi_hdd,
+ LMI_DiskDrive_DiskType_Hard_Disk_Drive);
+ } else if (rotational == 0) {
+ LMI_DiskDrive_Set_DiskType(&lmi_hdd,
+ LMI_DiskDrive_DiskType_Solid_State_Drive);
+ LMI_DiskDrive_Set_RPM(&lmi_hdd, 0);
+ } else {
+ LMI_DiskDrive_Set_DiskType(&lmi_hdd,
+ LMI_DiskDrive_DiskType_Other);
+ }
+ } else {
+ LMI_DiskDrive_Set_DiskType(&lmi_hdd,
+ LMI_DiskDrive_DiskType_Unknown);
+ }
+
+ if (basename[0] == 'h') {
+ LMI_DiskDrive_Set_InterconnectType(&lmi_hdd,
+ LMI_DiskDrive_InterconnectType_ATA);
+ } else if (basename[0] == 's') {
+ /* TODO: What about SAS? */
+ LMI_DiskDrive_Set_InterconnectType(&lmi_hdd,
+ LMI_DiskDrive_InterconnectType_SATA);
+ } else {
+ LMI_DiskDrive_Set_InterconnectType(&lmi_hdd,
+ LMI_DiskDrive_InterconnectType_Other);
+ }
+
+ KReturnInstance(cr, lmi_hdd);
+ }
+
+done:
+ smartctl_free_hdds(&smtcl_hdds, &smtcl_hdds_nb);
+ lsblk_free_hdds(&lsblk_hdds, &lsblk_hdds_nb);
+
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_DiskDriveGetInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ return KDefaultGetInstance(
+ _cb, mi, cc, cr, cop, properties);
+}
+
+static CMPIStatus LMI_DiskDriveCreateInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_DiskDriveModifyInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci,
+ const char** properties)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_DiskDriveDeleteInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_DiskDriveExecQuery(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* lang,
+ const char* query)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+CMInstanceMIStub(
+ LMI_DiskDrive,
+ LMI_DiskDrive,
+ _cb,
+ LMI_DiskDriveInitialize(ctx))
+
+static CMPIStatus LMI_DiskDriveMethodCleanup(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_DiskDriveInvokeMethod(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* meth,
+ const CMPIArgs* in,
+ CMPIArgs* out)
+{
+ return LMI_DiskDrive_DispatchMethod(
+ _cb, mi, cc, cr, cop, meth, in, out);
+}
+
+CMMethodMIStub(
+ LMI_DiskDrive,
+ LMI_DiskDrive,
+ _cb,
+ LMI_DiskDriveInitialize(ctx))
+
+KUint32 LMI_DiskDrive_RequestStateChange(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KUint16* RequestedState,
+ KRef* Job,
+ const KDateTime* TimeoutPeriod,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_SetPowerState(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KUint16* PowerState,
+ const KDateTime* Time,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_Reset(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_EnableDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KBoolean* Enabled,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_OnlineDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KBoolean* Online,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_QuiesceDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KBoolean* Quiesce,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_SaveProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_RestoreProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_DiskDrive_LockMedia(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_DiskDriveRef* self,
+ const KBoolean* Lock,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+/*
+ * Get CIM operational status according to smart status.
+ * @param smart_status from smartctl
+ * @return CIM id of operational status
+ */
+CMPIUint16 get_operational_status(const char *smart_status)
+{
+ static struct {
+ unsigned short cim_val; /* CIM value */
+ char *smart_status; /* smart status */
+ } values[] = {
+ {LMI_DiskDrive_OperationalStatus_Unknown, "UNKNOWN!"},
+ {LMI_DiskDrive_OperationalStatus_OK, "PASSED"},
+ {LMI_DiskDrive_OperationalStatus_Predictive_Failure, "FAILED!"},
+ };
+
+ size_t i, val_length = sizeof(values) / sizeof(values[0]);
+
+ for (i = 0; i < val_length; i++) {
+ if (strcmp(smart_status, values[i].smart_status) == 0) {
+ return values[i].cim_val;
+ }
+ }
+
+ return LMI_DiskDrive_OperationalStatus_Unknown;
+}
+
+/*
+ * Get CIM form factor according to reported disk value.
+ * @param form_factor from smartctl
+ * @return CIM id of form factor
+ */
+CMPIUint16 get_hdd_form_factor(const unsigned short form_factor)
+{
+ static struct {
+ unsigned short cim_val; /* CIM value */
+ unsigned short form_factor; /* form factor */
+ } values[] = {
+ {LMI_DiskDrive_FormFactor_Not_Reported, 0},
+ {LMI_DiskDrive_FormFactor_5_25_inch, 1},
+ {LMI_DiskDrive_FormFactor_3_5_inch, 2},
+ {LMI_DiskDrive_FormFactor_2_5_inch, 3},
+ {LMI_DiskDrive_FormFactor_1_8_inch, 4},
+ };
+
+ size_t i, val_length = sizeof(values) / sizeof(values[0]);
+
+ for (i = 0; i < val_length; i++) {
+ if (form_factor == values[i].form_factor) {
+ return values[i].cim_val;
+ }
+ }
+
+ return LMI_DiskDrive_FormFactor_Other;
+}
+
+KONKRET_REGISTRATION(
+ "root/cimv2",
+ "LMI_DiskDrive",
+ "LMI_DiskDrive",
+ "instance method")
diff --git a/src/hardware/LMI_DiskPhysicalPackageContainerProvider.c b/src/hardware/LMI_DiskPhysicalPackageContainerProvider.c
index ef6e41b..4518b4e 100644
--- a/src/hardware/LMI_DiskPhysicalPackageContainerProvider.c
+++ b/src/hardware/LMI_DiskPhysicalPackageContainerProvider.c
@@ -28,8 +28,9 @@
static const CMPIBroker* _cb;
-static void LMI_DiskPhysicalPackageContainerInitialize()
+static void LMI_DiskPhysicalPackageContainerInitialize(const CMPIContext *ctx)
{
+ lmi_init(provider_name, _cb, ctx, provider_config_defaults);
}
static CMPIStatus LMI_DiskPhysicalPackageContainerCleanup(
@@ -279,13 +280,13 @@ CMInstanceMIStub(
LMI_DiskPhysicalPackageContainer,
LMI_DiskPhysicalPackageContainer,
_cb,
- LMI_DiskPhysicalPackageContainerInitialize())
+ LMI_DiskPhysicalPackageContainerInitialize(ctx))
CMAssociationMIStub(
LMI_DiskPhysicalPackageContainer,
LMI_DiskPhysicalPackageContainer,
_cb,
- LMI_DiskPhysicalPackageContainerInitialize())
+ LMI_DiskPhysicalPackageContainerInitialize(ctx))
KONKRET_REGISTRATION(
"root/cimv2",
diff --git a/src/hardware/LMI_DiskPhysicalPackageProvider.c b/src/hardware/LMI_DiskPhysicalPackageProvider.c
index daa0133..3daac03 100644
--- a/src/hardware/LMI_DiskPhysicalPackageProvider.c
+++ b/src/hardware/LMI_DiskPhysicalPackageProvider.c
@@ -27,8 +27,9 @@
static const CMPIBroker* _cb = NULL;
-static void LMI_DiskPhysicalPackageInitialize()
+static void LMI_DiskPhysicalPackageInitialize(const CMPIContext *ctx)
{
+ lmi_init(provider_name, _cb, ctx, provider_config_defaults);
}
static CMPIStatus LMI_DiskPhysicalPackageCleanup(
@@ -188,7 +189,7 @@ CMInstanceMIStub(
LMI_DiskPhysicalPackage,
LMI_DiskPhysicalPackage,
_cb,
- LMI_DiskPhysicalPackageInitialize())
+ LMI_DiskPhysicalPackageInitialize(ctx))
static CMPIStatus LMI_DiskPhysicalPackageMethodCleanup(
CMPIMethodMI* mi,
@@ -215,7 +216,7 @@ CMMethodMIStub(
LMI_DiskPhysicalPackage,
LMI_DiskPhysicalPackage,
_cb,
- LMI_DiskPhysicalPackageInitialize())
+ LMI_DiskPhysicalPackageInitialize(ctx))
KUint32 LMI_DiskPhysicalPackage_IsCompatible(
const CMPIBroker* cb,
diff --git a/src/hardware/LMI_Hardware.h b/src/hardware/LMI_Hardware.h
index 6ca6ab2..52756ac 100644
--- a/src/hardware/LMI_Hardware.h
+++ b/src/hardware/LMI_Hardware.h
@@ -47,5 +47,6 @@ const char *provider_name;
#define PCI_DEVICE_CLASS_NAME "PCIDevice"
#define PCI_BRIDGE_CLASS_NAME "PCIBridge"
#define DISK_PHYS_PKG_CLASS_NAME "DiskPhysicalPackage"
+#define DISK_DRIVE_CLASS_NAME "DiskDrive"
#endif /* LMI_HARDWARE_H_ */
diff --git a/src/hardware/smartctl.c b/src/hardware/smartctl.c
index 1067e9b..5648ef0 100644
--- a/src/hardware/smartctl.c
+++ b/src/hardware/smartctl.c
@@ -32,6 +32,10 @@ void init_smctlhdd_struct(SmartctlHdd *hdd)
hdd->model = NULL;
hdd->serial_number = NULL;
hdd->name = NULL;
+ hdd->smart_status = NULL;
+ hdd->form_factor = 0;
+ hdd->port_speed = 0;
+ hdd->rpm = 0xffffffff;
}
/*
@@ -73,6 +77,11 @@ short check_smctlhdd_attributes(SmartctlHdd *hdd)
goto done;
}
}
+ if (!hdd->smart_status) {
+ if (!(hdd->smart_status = strdup("UNKNOWN!"))) {
+ goto done;
+ }
+ }
ret = 0;
@@ -188,7 +197,7 @@ short smartctl_get_hdds(SmartctlHdd **hdds, unsigned *hdds_nb)
for (curr_hdd = 0; curr_hdd < *hdds_nb; curr_hdd++) {
/* get smartctl output */
char command[PATH_MAX];
- snprintf(command, PATH_MAX, "smartctl -i %s",
+ snprintf(command, PATH_MAX, "smartctl -iH --identify=n %s",
(*hdds)[curr_hdd].dev_path);
if (run_command(command, &buffer, &buffer_size) != 0) {
continue;
@@ -217,6 +226,44 @@ short smartctl_get_hdds(SmartctlHdd **hdds, unsigned *hdds_nb)
buf = NULL;
continue;
}
+ /* SMART status */
+ buf = copy_string_part_after_delim(buffer[i],
+ "SMART overall-health self-assessment test result: ");
+ if (buf) {
+ (*hdds)[curr_hdd].smart_status = buf;
+ buf = NULL;
+ continue;
+ }
+ /* Form Factor */
+ /* Form Factor is stored in the 168. word
+ * of the IDENTIFY DEVICE data table. Line with this info looks like:
+ * 168 0x0003 Form factor */
+ buf = copy_string_part_after_delim(buffer[i], "168");
+ if (buf) {
+ sscanf(buf, "%hx", &(*hdds)[curr_hdd].form_factor);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
+ /* Port Speed */
+ buf = copy_string_part_after_delim(buffer[i], " (current: ");
+ if (buf) {
+ float speed;
+ sscanf(buf, "%f", &speed);
+ free(buf);
+ buf = NULL;
+ /* Gb/s -> b/s */
+ (*hdds)[curr_hdd].port_speed = round(speed * 1073741824);
+ continue;
+ }
+ /* RPM */
+ buf = copy_string_part_after_delim(buffer[i], "Rotation Rate:");
+ if (buf) {
+ sscanf(buf, "%u", &(*hdds)[curr_hdd].rpm);
+ free(buf);
+ buf = NULL;
+ continue;
+ }
}
free_2d_buffer(&buffer, &buffer_size);
@@ -261,6 +308,8 @@ void smartctl_free_hdds(SmartctlHdd **hdds, unsigned *hdds_nb)
(*hdds)[i].serial_number = NULL;
free((*hdds)[i].name);
(*hdds)[i].name = NULL;
+ free((*hdds)[i].smart_status);
+ (*hdds)[i].smart_status = NULL;
}
free(*hdds);
}
diff --git a/src/hardware/smartctl.h b/src/hardware/smartctl.h
index 5880e3a..560effa 100644
--- a/src/hardware/smartctl.h
+++ b/src/hardware/smartctl.h
@@ -26,6 +26,7 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
+#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "utils.h"
@@ -33,12 +34,16 @@
/* HDD from smartctl. */
typedef struct _SmartctlHdd {
- char *dev_path; /* /dev/path */
- char *dev_basename; /* basename of /dev/path */
- char *manufacturer; /* Manufacturer */
- char *model; /* Model */
- char *serial_number; /* Serial Number */
- char *name; /* Name */
+ char *dev_path; /* /dev/path */
+ char *dev_basename; /* basename of /dev/path */
+ char *manufacturer; /* Manufacturer */
+ char *model; /* Model */
+ char *serial_number; /* Serial Number */
+ char *name; /* Name */
+ char *smart_status; /* SMART status */
+ unsigned short form_factor; /* Form Factor */
+ unsigned long port_speed; /* Port Speed in b/s */
+ unsigned rpm; /* RPM of drive */
} SmartctlHdd;
/*