2018-01-08 20:59:48 +00:00
|
|
|
/*************************************************************************
|
|
|
|
* Copyright (C) 2018 by Caio Carvalho <caiojcarvalho@gmail.com> *
|
|
|
|
* *
|
|
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.*
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
#include "core/smartdiskinformation.h"
|
|
|
|
#include "core/smartattributeparseddata.h"
|
|
|
|
|
2018-04-09 16:16:02 +01:00
|
|
|
#include <memory>
|
|
|
|
|
2018-01-08 20:59:48 +00:00
|
|
|
static quint64 u64log2(quint64 n);
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Creates a new SmartDiskInformationObject */
|
2018-01-08 20:59:48 +00:00
|
|
|
SmartDiskInformation::SmartDiskInformation() :
|
|
|
|
m_ModelName(QString()),
|
|
|
|
m_FirmwareVersion(QString()),
|
|
|
|
m_SerialNumber(QString()),
|
|
|
|
m_Size(0),
|
|
|
|
m_Temperature(0),
|
|
|
|
m_BadSectors(0),
|
|
|
|
m_PoweredOn(0),
|
|
|
|
m_PowerCycles(0),
|
|
|
|
m_SmartStatus(false),
|
|
|
|
m_BadAttributeNow(false),
|
|
|
|
m_BadAttributeInThePast(false),
|
2018-04-09 15:37:46 +01:00
|
|
|
m_SelfTestExecutionStatus(SmartStatus::SelfTestStatus::Success),
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall(SmartStatus::Overall::Bad)
|
2018-01-08 20:59:48 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Update the number of bad sectors based on reallocated sector count and current pending sector attributes data */
|
2018-01-08 20:59:48 +00:00
|
|
|
void SmartDiskInformation::updateBadSectors()
|
|
|
|
{
|
2018-04-09 16:16:02 +01:00
|
|
|
std::unique_ptr<SmartAttributeParsedData> reallocatedSectorCt(findAttribute(5));
|
|
|
|
std::unique_ptr<SmartAttributeParsedData> currentPendingSector(findAttribute(197));
|
2018-01-08 20:59:48 +00:00
|
|
|
|
|
|
|
if (!reallocatedSectorCt && !currentPendingSector)
|
|
|
|
m_BadSectors = 0;
|
|
|
|
else if (reallocatedSectorCt && currentPendingSector)
|
|
|
|
m_BadSectors = reallocatedSectorCt->prettyValue() + currentPendingSector->prettyValue();
|
|
|
|
else if (reallocatedSectorCt)
|
|
|
|
m_BadSectors = reallocatedSectorCt->prettyValue();
|
|
|
|
else
|
|
|
|
m_BadSectors = currentPendingSector->prettyValue();
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Update SMART overall data based on the quantity of bad sectors and the status of SMART attributes */
|
2018-01-08 20:59:48 +00:00
|
|
|
void SmartDiskInformation::updateOverall()
|
|
|
|
{
|
|
|
|
if (!smartStatus()) {
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::Bad;
|
2018-01-08 20:59:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint64 sector_threshold = u64log2(size() / 512) * 1024;
|
|
|
|
|
|
|
|
if (badSectors() >= sector_threshold) {
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::BadSectorsMany;
|
2018-01-08 20:59:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
validateBadAttributes();
|
|
|
|
|
|
|
|
if (m_BadAttributeNow) {
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::BadNow;
|
2018-01-08 20:59:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (badSectors() > 0) {
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::BadSectors;
|
2018-01-08 20:59:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_BadAttributeInThePast) {
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::BadPast;
|
2018-01-08 20:59:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-09 15:27:07 +01:00
|
|
|
m_Overall = SmartStatus::Overall::Good;
|
2018-01-08 20:59:48 +00:00
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Update the temperature value based on SMART attributes
|
|
|
|
@return a boolean representing the status of the operation
|
|
|
|
*/
|
2018-01-08 20:59:48 +00:00
|
|
|
bool SmartDiskInformation::updateTemperature()
|
|
|
|
{
|
2018-04-09 16:16:02 +01:00
|
|
|
std::unique_ptr<SmartAttributeParsedData> temperatureCelsius(findAttribute(231));
|
|
|
|
std::unique_ptr<SmartAttributeParsedData> temperatureCelsius2(findAttribute(194));
|
|
|
|
std::unique_ptr<SmartAttributeParsedData> airflowTemperatureCelsius(findAttribute(190));
|
2018-01-08 20:59:48 +00:00
|
|
|
|
|
|
|
if (temperatureCelsius != nullptr
|
2018-04-05 23:06:52 +01:00
|
|
|
&& temperatureCelsius->prettyUnit() == SmartAttributeUnit::Milikelvin) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_Temperature = temperatureCelsius->prettyValue();
|
|
|
|
return true;
|
|
|
|
} else if (temperatureCelsius2 != nullptr
|
2018-04-05 23:06:52 +01:00
|
|
|
&& temperatureCelsius2->prettyUnit() == SmartAttributeUnit::Milikelvin) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_Temperature = temperatureCelsius2->prettyValue();
|
|
|
|
return true;
|
|
|
|
} else if (airflowTemperatureCelsius != nullptr
|
|
|
|
&& airflowTemperatureCelsius->prettyUnit() ==
|
2018-04-05 23:06:52 +01:00
|
|
|
SmartAttributeUnit::Milikelvin) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_Temperature = airflowTemperatureCelsius->prettyValue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Update the powered on value based on SMART attributes
|
|
|
|
@return a boolean representing the status of the operation
|
|
|
|
*/
|
2018-01-08 20:59:48 +00:00
|
|
|
bool SmartDiskInformation::updatePowerOn()
|
|
|
|
{
|
2018-04-09 16:16:02 +01:00
|
|
|
std::unique_ptr<SmartAttributeParsedData> powerOnHours(findAttribute(9));
|
|
|
|
std::unique_ptr<SmartAttributeParsedData> powerOnSeconds(findAttribute(233));
|
2018-01-08 20:59:48 +00:00
|
|
|
|
|
|
|
if (powerOnHours != nullptr
|
2018-04-05 23:06:52 +01:00
|
|
|
&& powerOnHours->prettyUnit() == SmartAttributeUnit::Miliseconds) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_PoweredOn = powerOnHours->prettyValue();
|
|
|
|
return true;
|
|
|
|
} else if (powerOnSeconds != nullptr
|
2018-04-05 23:06:52 +01:00
|
|
|
&& powerOnSeconds->prettyUnit() == SmartAttributeUnit::Miliseconds) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_PoweredOn = powerOnSeconds->prettyValue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Update the power cycles value based on SMART attributes
|
|
|
|
@return a boolean representing the status of the operation
|
|
|
|
*/
|
2018-01-08 20:59:48 +00:00
|
|
|
bool SmartDiskInformation::updatePowerCycle()
|
|
|
|
{
|
2018-04-09 16:16:02 +01:00
|
|
|
std::unique_ptr<SmartAttributeParsedData> powerCycleCount(findAttribute(12));
|
2018-01-08 20:59:48 +00:00
|
|
|
|
|
|
|
if (powerCycleCount != nullptr
|
2018-04-05 23:06:52 +01:00
|
|
|
&& powerCycleCount->prettyUnit() == SmartAttributeUnit::None) {
|
2018-01-08 20:59:48 +00:00
|
|
|
m_PowerCycles = powerCycleCount->prettyValue();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Validate disk attributes status */
|
2018-01-08 20:59:48 +00:00
|
|
|
void SmartDiskInformation::validateBadAttributes()
|
|
|
|
{
|
2018-01-09 04:35:59 +00:00
|
|
|
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
|
2018-01-08 20:59:48 +00:00
|
|
|
if (attribute.prefailure()) {
|
|
|
|
if (attribute.goodNowValid() && !attribute.goodNow())
|
|
|
|
m_BadAttributeNow = true;
|
|
|
|
if (attribute.goodInThePastValid() && !attribute.goodInThePast())
|
|
|
|
m_BadAttributeInThePast = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-11 20:38:53 +00:00
|
|
|
/** Search for a attribute based on its id number
|
|
|
|
@return a reference to the attribute
|
|
|
|
*/
|
2018-01-08 20:59:48 +00:00
|
|
|
SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id)
|
|
|
|
{
|
|
|
|
SmartAttributeParsedData *attr = nullptr;
|
2018-01-09 04:35:59 +00:00
|
|
|
for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) {
|
2018-01-08 20:59:48 +00:00
|
|
|
if (id == attribute.id()) {
|
|
|
|
attr = new SmartAttributeParsedData(attribute);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return attr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static quint64 u64log2(quint64 n)
|
|
|
|
{
|
|
|
|
quint64 r;
|
|
|
|
|
|
|
|
if (n <= 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
r = 0;
|
|
|
|
for (;;) {
|
|
|
|
n = n >> 1;
|
|
|
|
if (!n)
|
|
|
|
return r;
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|