From 84a2da8bc2dba4743757f1a8580ebbcda2de4391 Mon Sep 17 00:00:00 2001
From: localhorst <localhorst@mosad.xyz>
Date: Sat, 1 Jun 2024 14:52:50 +0200
Subject: [PATCH] reuse working smartclt cmd

---
 include/drive.h |  5 ++++
 src/drive.cpp   |  9 +++++++
 src/smart.cpp   | 66 +++++++++++++++++++++++++++++++++++--------------
 3 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/include/drive.h b/include/drive.h
index f1e28ab..4432ce7 100644
--- a/include/drive.h
+++ b/include/drive.h
@@ -45,6 +45,7 @@ private:
     double d32TaskPercentage = 0U;     // in percent for Shred (1 to 100)
     time_t u32TimestampTaskStart = 0U; // unix timestamp for duration of an action
     time_t u32TaskDuration = 0U;       // time needed to complete the task
+    string desiredSmartctlCommand;     //command used to gather S.M.A.R.T. values from drive
 
     struct
     {
@@ -77,6 +78,7 @@ public:
     uint32_t getPowerOnHours(void); // in hours
     uint32_t getPowerCycles(void);
     uint32_t getTemperature(void); // in Fahrenheit, just kidding: degree Celsius
+    
     void checkFrozenDrive(void);
 
     void setDriveSMARTData(string modelFamily,
@@ -100,6 +102,9 @@ public:
     void setActionStartTimestamp();
     time_t getActionStartTimestamp();
 
+    void setSmartcltCommand(string cmd);
+    string getSmartcltCommand(void);
+
     void calculateTaskDuration();
     time_t getTaskDuration();
 };
diff --git a/src/drive.cpp b/src/drive.cpp
index 1ca3e61..43cd793 100644
--- a/src/drive.cpp
+++ b/src/drive.cpp
@@ -161,6 +161,15 @@ time_t Drive::getActionStartTimestamp()
     return this->u32TimestampTaskStart;
 }
 
+void Drive::setSmartcltCommand(string cmd)
+{
+    this->desiredSmartctlCommand = cmd;
+}
+string Drive::getSmartcltCommand(void)
+{
+    return this->desiredSmartctlCommand;
+}
+
 void Drive::calculateTaskDuration()
 {
     time_t u32localtime;
diff --git a/src/smart.cpp b/src/smart.cpp
index 339d94f..d739333 100644
--- a/src/smart.cpp
+++ b/src/smart.cpp
@@ -27,27 +27,62 @@ void SMART::readSMARTData(Drive *drive)
     modelName.clear();
     serial.clear();
 
-    string sSmartctlCommands[] = {" --json -a ", " --json -d sntjmicron -a ", " --json -d sntasmedia -a ", " --json -d sntrealtek -a ", " --json -d sat -a "};
-
-    for (string sSmartctlCommand : sSmartctlCommands)
+    if (drive->getSmartcltCommand().empty())
     {
-        string sCMD = ("smartctl");
-        sCMD.append(sSmartctlCommand);
-        sCMD.append(drive->getPath());
-        const char *cpComand = sCMD.c_str();
+        // No working Smartctl command is known --> try all
+        string sSmartctlCommands[] = {" --json -a ", " --json -d sntjmicron -a ", " --json -d sntasmedia -a ", " --json -d sntrealtek -a ", " --json -d sat -a "};
 
-        // Logger::logThis()->info(cpComand);
+        for (string sSmartctlCommand : sSmartctlCommands)
+        {
+            string sCMD = ("smartctl");
+            sCMD.append(sSmartctlCommand);
+            sCMD.append(drive->getPath());
+            const char *cpComand = sCMD.c_str();
 
-        FILE *outputfileSmart = popen(cpComand, "r");
-        size_t len = 0U;     // length of found line
+            // Logger::logThis()->info(cpComand);
+
+            FILE *outputfileSmart = popen(cpComand, "r");
+            size_t len = 0U;    // length of found line
+            char *cLine = NULL; // found line
+            uint8_t status = 255U;
+
+            while ((getline(&cLine, &len, outputfileSmart)) != -1)
+            {
+                string sLine = string(cLine);
+
+                SMART::parseExitStatus(sLine, status);
+                SMART::parseModelFamily(sLine, modelFamily);
+                SMART::parseModelName(sLine, modelName);
+                SMART::parseSerial(sLine, serial);
+                SMART::parseCapacity(sLine, capacity);
+                SMART::parseErrorCount(sLine, errorCount);
+                SMART::parsePowerOnHours(sLine, powerOnHours);
+                SMART::parsePowerCycles(sLine, powerCycles);
+                SMART::parseTemperature(sLine, temperature);
+            }
+
+            pclose(outputfileSmart);
+
+            if (status == 0U)
+            {
+                // Found S.M.A.R.T. data with this command
+                // Logger::logThis()->info("Found S.M.A.R.T. data with this command");
+                drive->setSmartcltCommand(sCMD);
+                break;
+            }
+        }
+    }
+    else
+    {
+        // A working Smartctl command is known
+        FILE *outputfileSmart = popen(drive->getSmartcltCommand().c_str(), "r");
+        size_t len = 0U;    // length of found line
         char *cLine = NULL; // found line
-        uint8_t status = 255U;
 
         while ((getline(&cLine, &len, outputfileSmart)) != -1)
         {
             string sLine = string(cLine);
 
-            SMART::parseExitStatus(sLine, status);
             SMART::parseModelFamily(sLine, modelFamily);
             SMART::parseModelName(sLine, modelName);
             SMART::parseSerial(sLine, serial);
@@ -59,13 +94,6 @@ void SMART::readSMARTData(Drive *drive)
         }
 
         pclose(outputfileSmart);
-
-        if (status == 0U)
-        {
-            // Found S.M.A.R.T. data with this command
-            // Logger::logThis()->info("Found S.M.A.R.T. data with this command");
-            break;
-        }
     }
 
     drive->setDriveSMARTData(modelFamily, modelName, serial, capacity, errorCount, powerOnHours, powerCycles, temperature); // write data in drive