Merge pull request 'version 0.3.0' (#52) from develop into master

Reviewed-on: #52
This commit is contained in:
Hendrik Schutter 2022-09-20 21:56:04 +02:00
commit 573a0df080
17 changed files with 324 additions and 119 deletions

5
.gitignore vendored
View File

@ -41,7 +41,10 @@
reHDD reHDD
reHDD.log *.log
*.ods
*.txt
.vscode/
ignoreDrives.conf ignoreDrives.conf

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "tfnoisegen"]
path = tfnoisegen
url = https://git.mosad.xyz/localhorst/tfnoisegen.git

View File

@ -11,6 +11,8 @@
## Debian Build Notes ## Debian Build Notes
* `apt-get install ncurses-dev git make g++` * `apt-get install ncurses-dev git make g++`
* `git submodule init`
* `git submodule update`
* `make release` * `make release`
## Create Standalone with Debian 11 ## Create Standalone with Debian 11
@ -22,13 +24,18 @@ Instructions how to create a standalone machine that boots directly to reHDD. Th
* Upload reHDD log every 12h if wanted * Upload reHDD log every 12h if wanted
### Software requirements ### Software requirements
* `apt-get install hwinfo smartmontools curl` * `apt-get install hwinfo smartmontools curl htop sudo`
### Installation ### Installation
clone this repo into /root/ clone this repo into /root/
```
git submodule init
git submodule update
```
`cd /root/reHDD/` `cd /root/reHDD/`
`make release` `make release`

View File

@ -1,2 +1,3 @@
4673974d 4673974d
2cb3dea4 2cb3dea4
8ffbc421

View File

@ -22,6 +22,14 @@ public:
FROZEN FROZEN
} state; } state;
struct
{
time_t u32ShredTimeDelta;
std::chrono::time_point<std::chrono::system_clock> chronoShredTimestamp;
unsigned long ulWrittenBytes;
unsigned long ulSpeedMetricBytesWritten;
} sShredSpeed;
bool bWasShredded = false; bool bWasShredded = false;
bool bWasDeleteted = false; bool bWasDeleteted = false;
bool bIsOffline = false; bool bIsOffline = false;
@ -29,18 +37,23 @@ public:
private: private:
string sPath; string sPath;
string sModelFamily;
string sModelName;
string sSerial;
uint64_t u64Capacity = 0U; //in byte
uint32_t u32ErrorCount = 0U;
uint32_t u32PowerOnHours = 0U; //in hours
uint32_t u32PowerCycles = 0U;
time_t u32Timestamp = 0U; //unix timestamp for detecting a frozen drive time_t u32Timestamp = 0U; //unix timestamp for detecting a frozen drive
double d32TaskPercentage = 0U; //in percent for Shred (1 to 100) double d32TaskPercentage = 0U; //in percent for Shred (1 to 100)
time_t u32TimestampTaskStart = 0U; //unix timestamp for duration of an action time_t u32TimestampTaskStart = 0U; //unix timestamp for duration of an action
time_t u32TaskDuration = 0U; //time needed to complete the task time_t u32TaskDuration = 0U; //time needed to complete the task
struct
{
string sModelFamily;
string sModelName;
string sSerial;
uint64_t u64Capacity = 0U; //in byte
uint32_t u32ErrorCount = 0U;
uint32_t u32PowerOnHours = 0U; //in hours
uint32_t u32PowerCycles = 0U;
uint32_t u32Temperature = 0U; //in Fahrenheit, just kidding: degree Celsius
} sSmartData;
private: private:
void setTimestamp(); void setTimestamp();
@ -60,6 +73,7 @@ public:
uint32_t getErrorCount(void); uint32_t getErrorCount(void);
uint32_t getPowerOnHours(void); //in hours uint32_t getPowerOnHours(void); //in hours
uint32_t getPowerCycles(void); uint32_t getPowerCycles(void);
uint32_t getTemperature(void); //in Fahrenheit, just kidding: degree Celsius
void checkFrozenDrive(void); void checkFrozenDrive(void);
void setDriveSMARTData( string modelFamily, void setDriveSMARTData( string modelFamily,
@ -68,12 +82,14 @@ public:
uint64_t capacity, uint64_t capacity,
uint32_t errorCount, uint32_t errorCount,
uint32_t powerOnHours, uint32_t powerOnHours,
uint32_t powerCycles); uint32_t powerCycles,
uint32_t temperature);
string sCapacityToText(); string sCapacityToText();
string sErrorCountToText(); string sErrorCountToText();
string sPowerOnHoursToText(); string sPowerOnHoursToText();
string sPowerCyclesToText(); string sPowerCyclesToText();
string sTemperatureToText();
void setTaskPercentage(double d32TaskPercentage); void setTaskPercentage(double d32TaskPercentage);
double getTaskPercentage(void); double getTaskPercentage(void);

View File

@ -8,13 +8,15 @@
#ifndef REHDD_H_ #ifndef REHDD_H_
#define REHDD_H_ #define REHDD_H_
#define REHDD_VERSION "bV0.2.2" #define REHDD_VERSION "bV0.3.0"
// Drive handling Settings // Drive handling Settings
#define WORSE_HOURS 19200 //mark drive if at this limit or beyond #define WORSE_HOURS 19200 //mark drive if at this limit or beyond
#define WORSE_POWERUP 10000 //mark drive if at this limit or beyond #define WORSE_POWERUP 10000 //mark drive if at this limit or beyond
#define WORSE_TEMPERATURE 55 //mark drive if at this limit or beyond
#define SHRED_ITERATIONS 3U #define SHRED_ITERATIONS 3U
#define FROZEN_TIMEOUT 10 //After this timeout (minutes) the drive will be marked as frozen #define FROZEN_TIMEOUT 20 //After this timeout (minutes) the drive will be marked as frozen, if no progress
#define METRIC_THRESHOLD 3L*1000L*1000L*1000L //calc shred speed with this minimum of time delta
// Logger Settings // Logger Settings
#define LOG_PATH "./reHDD.log" #define LOG_PATH "./reHDD.log"
@ -83,12 +85,14 @@ private:
static void searchDrives(list <Drive>* plistDrives); static void searchDrives(list <Drive>* plistDrives);
static void printDrives(list <Drive>* plistDrives); static void printDrives(list <Drive>* plistDrives);
static void filterIgnoredDrives(list <Drive>* plistDrives); static void startShredAllDrives(list <Drive>* plistDrives);
static void updateShredMetrics(list <Drive>* plistDrives);
static void filterIgnoredDrives(list <Drive>* plistDrives);
static void filterNewDrives(list <Drive>* plistOldDrives, list <Drive>* plistNewDrives); static void filterNewDrives(list <Drive>* plistOldDrives, list <Drive>* plistNewDrives);
static void addSMARTData(list <Drive>* plistDrives); static void addSMARTData(list <Drive>* plistDrives);
static void ThreadScannDevices(); static void ThreadScannDevices();
static void ThreadUserInput(); static void ThreadUserInput();
static void ThreadShred(); static void ThreadShred(Drive* const pDrive);
static void ThreadDelete(); static void ThreadDelete();
static void ThreadCheckFrozenDrives(); static void ThreadCheckFrozenDrives();
static void handleArrowKey(TUI::UserInput userInput); static void handleArrowKey(TUI::UserInput userInput);

View File

@ -17,11 +17,13 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#define CHUNK_SIZE 1024*1024*2 //amount of bytes that are overwritten at once --> 2MB
#define CHUNK_DIMENSION 100U //amount of chunks are read at once from random source #define CHUNK_SIZE 1024*1024*32 //amount of bytes that are overwritten at once --> 32MB
#define TFNG_DATA_SIZE CHUNK_SIZE //amount of bytes used by tfng
//#define DEMO_DRIVE_SIZE 1024*1024*256L // 256MB //#define DEMO_DRIVE_SIZE 1024*1024*256L // 256MB
//#define DEMO_DRIVE_SIZE 1024*1024*1024L // 1GB //#define DEMO_DRIVE_SIZE 1024*1024*1024L // 1GB
//#define DEMO_DRIVE_SIZE 5*1024*1024*1024L // 5GB
//#define DEMO_DRIVE_SIZE 1024*1024*1024*10L // 10GB //#define DEMO_DRIVE_SIZE 1024*1024*1024*10L // 10GB
typedef int fileDescriptor; typedef int fileDescriptor;
@ -39,7 +41,8 @@ public:
private: private:
fileDescriptor randomSrcFileDiscr; fileDescriptor randomSrcFileDiscr;
fileDescriptor driveFileDiscr; fileDescriptor driveFileDiscr;
unsigned char caChunk[CHUNK_DIMENSION][CHUNK_SIZE]; unsigned char caTfngData[TFNG_DATA_SIZE];
unsigned char caReadBuffer[CHUNK_SIZE];
unsigned long ulDriveByteSize; unsigned long ulDriveByteSize;
unsigned long ulDriveByteOverallCount = 0; //all bytes shredded in all iterations + checking -> used for progress calculation unsigned long ulDriveByteOverallCount = 0; //all bytes shredded in all iterations + checking -> used for progress calculation
double d32Percent = 0.0; double d32Percent = 0.0;

View File

@ -27,6 +27,7 @@ private:
static void parseErrorCount(string sLine); static void parseErrorCount(string sLine);
static void parsePowerOnHours(string sLine); static void parsePowerOnHours(string sLine);
static void parsePowerCycle(string sLine); static void parsePowerCycle(string sLine);
static void parseTemperature(string sLine);
static string modelFamily; static string modelFamily;
static string modelName; static string modelName;
@ -35,6 +36,7 @@ private:
static uint32_t errorCount; static uint32_t errorCount;
static uint32_t powerOnHours; static uint32_t powerOnHours;
static uint32_t powerCycle; static uint32_t powerCycle;
static uint32_t temperature;
}; };
#endif // SMART_H_ #endif // SMART_H_

View File

@ -22,7 +22,7 @@ protected:
public: public:
enum UserInput { UpKey, DownKey, Abort, Shred, Delete, Enter, ESC, Undefined}; enum UserInput { UpKey, DownKey, Abort, Shred, ShredAll, Delete, Enter, ESC, Undefined};
struct MenuState struct MenuState
{ {
bool bAbort; bool bAbort;
@ -56,16 +56,17 @@ private:
static WINDOW *createOverViewWindow( int iXSize, int iYSize); static WINDOW *createOverViewWindow( int iXSize, int iYSize);
static WINDOW *createDetailViewWindow( int iXSize, int iYSize, int iXStart, Drive drive); static WINDOW *createDetailViewWindow( int iXSize, int iYSize, int iXStart, Drive drive);
static WINDOW *overwriteDetailViewWindow( int iXSize, int iYSize, int iXStart); static WINDOW *overwriteDetailViewWindow( int iXSize, int iYSize, int iXStart);
static WINDOW *createEntryWindow(int iXSize, int iYSize, int iXStart, int iYStart, string sModelFamily, string sModelName, string sCapacity, string sState, string sTime, bool bSelected); static WINDOW *createEntryWindow(int iXSize, int iYSize, int iXStart, int iYStart, int iListIndex, string sModelFamily, string sSerial, string sCapacity, string sState, string sTime, string sSpeed, string sTemp, bool bSelected);
static WINDOW *createSystemStats(int iXSize, int iYSize, int iXStart, int iYStart); static WINDOW *createSystemStats(int iXSize, int iYSize, int iXStart, int iYStart);
static WINDOW *createMenuView(int iXSize, int iYSize, int iXStart, int iYStart, struct MenuState menustate); static WINDOW *createMenuView(int iXSize, int iYSize, int iXStart, int iYStart, struct MenuState menustate);
static WINDOW *createDialog(int iXSize, int iYSize, int iXStart, int iYStart, string selectedTask, string optionA, string optionB); static WINDOW *createDialog(int iXSize, int iYSize, int iXStart, int iYStart, string selectedTask, string optionA, string optionB);
static WINDOW* createFrozenWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, string sModelFamily, string sModelName, string sSerial, string sProgress); static WINDOW* createFrozenWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, string sModelFamily, string sModelName, string sSerial, string sProgress);
static WINDOW* createSmartWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, uint32_t u32PowerOnHours, uint32_t u32PowerCycles, uint32_t u32ErrorCount); static WINDOW* createSmartWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, uint32_t u32PowerOnHours, uint32_t u32PowerCycles, uint32_t u32ErrorCount, uint32_t u32Temperature);
static WINDOW* createZeroChecksumWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, string sModelFamily, string sModelName, string sSerial, uint32_t u32Checksum); static WINDOW* createZeroChecksumWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, string sModelFamily, string sModelName, string sSerial, uint32_t u32Checksum);
void displaySelectedDrive(Drive drive, int stdscrX, int stdscrY); void displaySelectedDrive(Drive drive, int stdscrX, int stdscrY);
string formatTimeDuration(time_t u32Duration); string formatTimeDuration(time_t u32Duration);
string formatSpeed(time_t u32ShredTimeDelta, unsigned long ulWrittenBytes);
}; };
#endif // TUI_H_ #endif // TUI_H_

View File

@ -8,19 +8,22 @@ SRC_EXT = cpp
# Path to the source directory, relative to the makefile # Path to the source directory, relative to the makefile
SRC_PATH = src SRC_PATH = src
# Space-separated pkg-config libraries used by this project # Space-separated pkg-config libraries used by this project
LIBS = LIBS = lib
# General compiler flags # General compiler flags
COMPILE_FLAGS = -std=c++17 -Wall -Wextra -g COMPILE_FLAGS = -std=c++17 -Wall -Wextra -g
# Additional release-specific flags # Additional release-specific flags
RCOMPILE_FLAGS = -D NDEBUG RCOMPILE_FLAGS = -D NDEBUG -O3
# Additional debug-specific flags # Additional debug-specific flags
DCOMPILE_FLAGS = -D DEBUG DCOMPILE_FLAGS = -D DEBUG
# Add additional include paths # Add additional include paths
INCLUDES = include INCLUDES = include
# General linker settings # General linker settings
LINK_FLAGS = -lpthread -lncurses LINK_FLAGS = -Llib -lpthread -lncurses -ltfng
# Doc # Doc
DOCDIR = doc DOCDIR = doc
TFRANDDIR = tfnoisegen
TFRANDLIB = libtfng.a
#### END PROJECT SETTINGS #### #### END PROJECT SETTINGS ####
# Optionally you may move the section above to a separate config.mk file, and # Optionally you may move the section above to a separate config.mk file, and
@ -158,6 +161,7 @@ dirs:
@echo "Creating directories" @echo "Creating directories"
@mkdir -p $(dir $(OBJECTS)) @mkdir -p $(dir $(OBJECTS))
@mkdir -p $(BIN_PATH) @mkdir -p $(BIN_PATH)
@mkdir -p $(LIBS)
# Removes all build files # Removes all build files
.PHONY: clean .PHONY: clean
@ -167,16 +171,22 @@ clean:
@echo "Deleting directories" @echo "Deleting directories"
@$(RM) -r build @$(RM) -r build
@$(RM) -r bin @$(RM) -r bin
@$(RM) -r $(LIBS)
@$(RM) -f reHDD.log @$(RM) -f reHDD.log
$(MAKE) clean -C tfnoisegen
# Main rule, checks the executable and symlinks to the output # Main rule, checks the executable and symlinks to the output
all: $(BIN_PATH)/$(BIN_NAME) all: $(BIN_PATH)/$(BIN_NAME)
$(MAKE) libtfng.a -C tfnoisegen
@cp $(TFRANDDIR)/$(TFRANDLIB) $(LIBS)
@echo "Making symlink: $(BIN_NAME) -> $<" @echo "Making symlink: $(BIN_NAME) -> $<"
@$(RM) $(BIN_NAME) @$(RM) $(BIN_NAME)
@ln -s $(BIN_PATH)/$(BIN_NAME) $(BIN_NAME) @ln -s $(BIN_PATH)/$(BIN_NAME) $(BIN_NAME)
# Link the executable # Link the executable
$(BIN_PATH)/$(BIN_NAME): $(OBJECTS) $(BIN_PATH)/$(BIN_NAME): $(OBJECTS)
$(MAKE) libtfng.a -C tfnoisegen
@cp $(TFRANDDIR)/$(TFRANDLIB) $(LIBS)
@echo "Linking: $@" @echo "Linking: $@"
@$(START_TIME) @$(START_TIME)
$(CMD_PREFIX)$(CXX) $(OBJECTS) $(LDFLAGS) -o $@ $(CMD_PREFIX)$(CXX) $(OBJECTS) $(LDFLAGS) -o $@

View File

@ -2,15 +2,17 @@
echo starting update echo starting update
systemctl stop /lib/systemd/system/getty@tty1.service.d
cd /root/reHDD/
FILE=./ignoreDrives.conf FILE=./ignoreDrives.conf
if test -f "$FILE"; then if test -f "$FILE"; then
echo backup exits echo backup exits
else else
cp reHDD/ignoreDrives.conf ./ignoreDrives.conf cp /root/reHDD/ignoreDrives.conf /root/ignoreDrives.conf
fi fi
cd reHDD
git reset git reset
git stash force git stash force
@ -23,4 +25,6 @@ git pull
make release make release
cp ../ignoreDrives.conf ./ cp /root/ignoreDrives.conf /root/reHDD/ignoreDrives.conf
systemctl start /lib/systemd/system/getty@tty1.service.d

View File

@ -14,36 +14,41 @@ string Drive::getPath(void)
string Drive::getModelFamily(void) string Drive::getModelFamily(void)
{ {
return sModelFamily; return sSmartData.sModelFamily;
} }
string Drive::getModelName(void) string Drive::getModelName(void)
{ {
return sModelName; return sSmartData.sModelName;
} }
string Drive::getSerial(void) string Drive::getSerial(void)
{ {
return sSerial; return sSmartData.sSerial;
} }
uint64_t Drive::getCapacity(void) uint64_t Drive::getCapacity(void)
{ {
return u64Capacity; return sSmartData.u64Capacity;
} }
uint32_t Drive::getErrorCount(void) uint32_t Drive::getErrorCount(void)
{ {
return u32ErrorCount; return sSmartData.u32ErrorCount;
} }
uint32_t Drive::getPowerOnHours(void) uint32_t Drive::getPowerOnHours(void)
{ {
return u32PowerOnHours; return sSmartData.u32PowerOnHours;
} }
uint32_t Drive::getPowerCycles(void) uint32_t Drive::getPowerCycles(void)
{ {
return u32PowerCycles; return sSmartData.u32PowerCycles;
}
uint32_t Drive::getTemperature(void)
{
return sSmartData.u32Temperature;
} }
string Drive::sCapacityToText() string Drive::sCapacityToText()
@ -67,7 +72,6 @@ string Drive::sErrorCountToText()
return to_string(getErrorCount()); return to_string(getErrorCount());
} }
string Drive::sPowerOnHoursToText() string Drive::sPowerOnHoursToText()
{ {
double dDays = 0U; double dDays = 0U;
@ -92,6 +96,11 @@ string Drive::sPowerCyclesToText()
return to_string(getPowerCycles()); return to_string(getPowerCycles());
} }
string Drive::sTemperatureToText()
{
return to_string(getTemperature())+" C";;
}
void Drive::setTaskPercentage(double d32TaskPercentage) void Drive::setTaskPercentage(double d32TaskPercentage)
{ {
if(d32TaskPercentage <= 100) if(d32TaskPercentage <= 100)
@ -115,6 +124,7 @@ double Drive::getTaskPercentage(void)
* \param uint32_t errorCount * \param uint32_t errorCount
* \param uint32_t powerOnHours * \param uint32_t powerOnHours
* \param uint32_t powerCycle * \param uint32_t powerCycle
* \param uint32_t temperature
* \return void * \return void
*/ */
void Drive::setDriveSMARTData( string modelFamily, void Drive::setDriveSMARTData( string modelFamily,
@ -123,16 +133,17 @@ void Drive::setDriveSMARTData( string modelFamily,
uint64_t capacity, uint64_t capacity,
uint32_t errorCount, uint32_t errorCount,
uint32_t powerOnHours, uint32_t powerOnHours,
uint32_t powerCycle) uint32_t powerCycle,
uint32_t temperature)
{ {
this->sModelFamily = modelFamily; this->sSmartData.sModelFamily = modelFamily;
sModelName = modelName; this->sSmartData.sModelName = modelName;
sSerial = serial; this->sSmartData.sSerial = serial;
u64Capacity = capacity; this->sSmartData.u64Capacity = capacity;
u32ErrorCount = errorCount; this->sSmartData.u32ErrorCount = errorCount;
u32PowerOnHours = powerOnHours; this->sSmartData.u32PowerOnHours = powerOnHours;
u32PowerCycles = powerCycle; this->sSmartData.u32PowerCycles = powerCycle;
this->sSmartData.u32Temperature = temperature;
} }
void Drive::setTimestamp() void Drive::setTimestamp()
@ -168,7 +179,7 @@ void Drive::checkFrozenDrive(void)
time_t u32localtime; time_t u32localtime;
time(&u32localtime); time(&u32localtime);
if((u32localtime - this->u32Timestamp) >= (FROZEN_TIMEOUT*60) && (this->u32Timestamp > 0)) if((u32localtime - this->u32Timestamp) >= (FROZEN_TIMEOUT*60) && (this->u32Timestamp > 0) && (this->getTaskPercentage() < 100.0))
{ {
Logger::logThis()->warning("Drive Frozen: " + this->getModelName() + " " + this->getSerial()); Logger::logThis()->warning("Drive Frozen: " + this->getModelName() + " " + this->getSerial());
this->bWasDeleteted = false; this->bWasDeleteted = false;

View File

@ -11,7 +11,7 @@ static int fdNewDrivesInformPipe[2];//File descriptor for pipe that informs if n
static int fdShredInformPipe[2];//File descriptor for pipe that informs if a wipe thread signals static int fdShredInformPipe[2];//File descriptor for pipe that informs if a wipe thread signals
static std::mutex mxScannDrives; static std::mutex mxDrives;
list <Drive> listNewDrives; //store found drives that are updated every 5sec list <Drive> listNewDrives; //store found drives that are updated every 5sec
@ -60,20 +60,25 @@ void reHDD::app_logic(void)
if(FD_ISSET(fdNewDrivesInformPipe[0], &selectSet)) if(FD_ISSET(fdNewDrivesInformPipe[0], &selectSet))
{ {
mxScannDrives.lock(); mxDrives.lock();
char dummy; char dummy;
read (fdNewDrivesInformPipe[0],&dummy,1); read (fdNewDrivesInformPipe[0],&dummy,1);
filterNewDrives(&listDrives, &listNewDrives); //filter and copy to app logic vector filterNewDrives(&listDrives, &listNewDrives); //filter and copy to app logic vector
printDrives(&listDrives); printDrives(&listDrives);
mxScannDrives.unlock(); mxDrives.unlock();
} }
if(FD_ISSET(fdShredInformPipe[0], &selectSet)) if(FD_ISSET(fdShredInformPipe[0], &selectSet))
{ {
char dummy; char dummy;
read (fdShredInformPipe[0],&dummy,1); read (fdShredInformPipe[0],&dummy,1);
updateShredMetrics(&listDrives);
#ifdef LOG_LEVEL_HIGH #ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("got progress signal from a shred task"); Logger::logThis()->info("got progress signal from a shred task");
#endif #endif
} }
ui->updateTUI(&listDrives, u8SelectedEntry); ui->updateTUI(&listDrives, u8SelectedEntry);
} //endless loop } //endless loop
@ -101,12 +106,12 @@ void reHDD::ThreadScannDevices()
{ {
while(true) while(true)
{ {
mxScannDrives.lock(); mxDrives.lock();
listNewDrives.clear(); listNewDrives.clear();
searchDrives(&listNewDrives); //search for new drives and store them in list searchDrives(&listNewDrives); //search for new drives and store them in list
filterIgnoredDrives(&listNewDrives); //filter out ignored drives filterIgnoredDrives(&listNewDrives); //filter out ignored drives
addSMARTData(&listNewDrives); //add S.M.A.R.T. Data to the drives addSMARTData(&listNewDrives); //add S.M.A.R.T. Data to the drives
mxScannDrives.unlock(); mxDrives.unlock();
write(fdNewDrivesInformPipe[1], "A",1); write(fdNewDrivesInformPipe[1], "A",1);
sleep(5); //sleep 5 sec sleep(5); //sleep 5 sec
} }
@ -116,7 +121,7 @@ void reHDD::ThreadCheckFrozenDrives()
{ {
while(true) while(true)
{ {
mxScannDrives.lock(); mxDrives.lock();
for(auto it = begin(listDrives); it != end(listDrives); ++it) for(auto it = begin(listDrives); it != end(listDrives); ++it)
{ {
if(it->state == Drive::SHRED_ACTIVE) if(it->state == Drive::SHRED_ACTIVE)
@ -124,7 +129,7 @@ void reHDD::ThreadCheckFrozenDrives()
it->checkFrozenDrive(); it->checkFrozenDrive();
} }
} }
mxScannDrives.unlock(); mxDrives.unlock();
sleep(13); //sleep 13 sec sleep(13); //sleep 13 sec
} }
} }
@ -164,6 +169,7 @@ void reHDD::ThreadUserInput()
getSelectedDrive()->state = Drive::DELETE_SELECTED; getSelectedDrive()->state = Drive::DELETE_SELECTED;
} }
} }
ui->updateTUI(&listDrives, u8SelectedEntry); ui->updateTUI(&listDrives, u8SelectedEntry);
break; break;
case TUI::UserInput::Shred: case TUI::UserInput::Shred:
@ -176,6 +182,12 @@ void reHDD::ThreadUserInput()
getSelectedDrive()->state = Drive::SHRED_SELECTED; getSelectedDrive()->state = Drive::SHRED_SELECTED;
} }
} }
ui->updateTUI(&listDrives, u8SelectedEntry);
break;
case TUI::UserInput::ShredAll:
//cout << "ShredAll" << endl;
startShredAllDrives(&listDrives);
ui->updateTUI(&listDrives, u8SelectedEntry); ui->updateTUI(&listDrives, u8SelectedEntry);
break; break;
case TUI::UserInput::Enter: case TUI::UserInput::Enter:
@ -194,13 +206,13 @@ void reHDD::ThreadUserInput()
} }
} }
void reHDD::ThreadShred() void reHDD::ThreadShred(Drive* const pDrive)
{ {
if (getSelectedDrive() != nullptr) if (pDrive != nullptr)
{ {
getSelectedDrive()->setActionStartTimestamp(); //save timestamp at start of shredding pDrive->setActionStartTimestamp(); //save timestamp at start of shredding
Shred* pShredTask = new Shred(); //create new shred task Shred* pShredTask = new Shred(); //create new shred task
pShredTask->shredDrive(getSelectedDrive(), &fdShredInformPipe[1]); //start new shred task pShredTask->shredDrive(pDrive, &fdShredInformPipe[1]); //start new shred task
delete pShredTask; //delete shred task delete pShredTask; //delete shred task
ui->updateTUI(&listDrives, u8SelectedEntry); ui->updateTUI(&listDrives, u8SelectedEntry);
} }
@ -246,12 +258,14 @@ void reHDD::filterNewDrives(list <Drive>* plistOldDrives, list <Drive>* plistNew
//search offline drives and mark them //search offline drives and mark them
for (itOld = plistOldDrives->begin(); itOld != plistOldDrives->end(); ++itOld) for (itOld = plistOldDrives->begin(); itOld != plistOldDrives->end(); ++itOld)
{ {
itOld->bIsOffline = true; //set offline befor seachring in the new list itOld->bIsOffline = true; //set offline before searching in the new list
for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end();) for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end();)
{ {
if((itOld->getSerial() == itNew->getSerial()) || (itOld->getPath() == itNew->getPath())) if((itOld->getSerial() == itNew->getSerial()) || (itOld->getPath() == itNew->getPath()))
{ {
itOld->bIsOffline = false; //drive is still attached itOld->bIsOffline = false; //drive is still attached
//copy new smart data to existing drive
itOld->setDriveSMARTData(itNew->getModelFamily(), itNew->getModelName(), itNew->getSerial(), itNew->getCapacity(), itNew->getErrorCount(), itNew->getPowerOnHours(), itNew->getPowerCycles(), itNew->getTemperature());
#ifdef LOG_LEVEL_HIGH #ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("Delete new drive, because allready attached: " + itNew->getModelName()); Logger::logThis()->info("Delete new drive, because allready attached: " + itNew->getModelName());
#endif #endif
@ -279,7 +293,7 @@ void reHDD::filterNewDrives(list <Drive>* plistOldDrives, list <Drive>* plistNew
for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end(); ++itNew) for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end(); ++itNew)
{ {
plistOldDrives->push_back(*itNew); plistOldDrives->push_back(*itNew);
Logger::logThis()->info("Add new drive: " + itNew->getModelName()); //Logger::logThis()->info("Add new drive: " + itNew->getModelName());
} }
plistNewDrives->clear(); plistNewDrives->clear();
} }
@ -291,7 +305,7 @@ void reHDD::filterNewDrives(list <Drive>* plistOldDrives, list <Drive>* plistNew
*/ */
void reHDD::searchDrives(list <Drive>* plistDrives) void reHDD::searchDrives(list <Drive>* plistDrives)
{ {
Logger::logThis()->info("--> search drives <--"); //Logger::logThis()->info("--> search drives <--");
char * cLine = NULL; char * cLine = NULL;
size_t len = 0; size_t len = 0;
@ -329,7 +343,7 @@ void reHDD::filterIgnoredDrives(list <Drive>* plistDrives)
for(string sLine; getline( input, sLine );) for(string sLine; getline( input, sLine );)
{ {
Logger::logThis()->info("read uuid: " + sLine); //Logger::logThis()->info("read uuid: " + sLine);
vtlIgnoredDevices.emplace_back(sLine); //add found path and uuid from ignore file to vector vtlIgnoredDevices.emplace_back(sLine); //add found path and uuid from ignore file to vector
} }
//loop through found entries in ingnore file //loop through found entries in ingnore file
@ -377,6 +391,32 @@ void reHDD::filterIgnoredDrives(list <Drive>* plistDrives)
} }
} }
/**
* \brief start shred for all drives
* \param pointer of list <Drive>* plistDrives
* \return void
*/
void reHDD::startShredAllDrives(list <Drive>* plistDrives)
{
list <Drive>::iterator it;
mxDrives.lock();
for (it = plistDrives->begin(); it != plistDrives->end(); ++it)
{
if(it->state == Drive::NONE)
{
Drive* pTmpDrive = iterator_to_pointer<Drive, std::list<Drive>::iterator > (it);
#ifdef LOG_LEVEL_HIGH
ostringstream address;
address << (void const *)&(*pTmpDrive);
Logger::logThis()->info("Started shred (all) for: " + pTmpDrive->getModelName() + "-" + pTmpDrive->getSerial() + " @" + address.str());
#endif
pTmpDrive->state = Drive::TaskState::SHRED_ACTIVE;
thread(ThreadShred, pTmpDrive).detach();
}
}
mxDrives.unlock();
}
/** /**
* \brief print drives with all information * \brief print drives with all information
* \param pointer of list <Drive>* plistDrives * \param pointer of list <Drive>* plistDrives
@ -412,6 +452,33 @@ void reHDD::printDrives(list <Drive>* plistDrives)
#endif #endif
} }
/**
* \brief update shred metrics for all drives
* \param pointer of list <Drive>* plistDrives
* \return void
*/
void reHDD::updateShredMetrics(list <Drive>* plistDrives)
{
list <Drive>::iterator it;
for (it = plistDrives->begin(); it != plistDrives->end(); ++it)
{
if(it->state == Drive::SHRED_ACTIVE)
{
Drive* pTmpDrive = iterator_to_pointer<Drive, std::list<Drive>::iterator > (it);
//set metrics for calculating shred speed
std::chrono::time_point<std::chrono::system_clock> chronoCurrentTimestamp = std::chrono::system_clock::now();
time_t u32ShredTimeDelta = (chronoCurrentTimestamp - pTmpDrive->sShredSpeed.chronoShredTimestamp).count();
if(u32ShredTimeDelta > METRIC_THRESHOLD)
{
pTmpDrive->sShredSpeed.u32ShredTimeDelta = u32ShredTimeDelta;
pTmpDrive->sShredSpeed.chronoShredTimestamp = std::chrono::system_clock::now();
pTmpDrive->sShredSpeed.ulWrittenBytes = pTmpDrive->sShredSpeed.ulSpeedMetricBytesWritten;
pTmpDrive->sShredSpeed.ulSpeedMetricBytesWritten = 0U;
}
}
}
}
/** /**
* \brief add S.M.A.R.T data from SMART * \brief add S.M.A.R.T data from SMART
* \param pointer of list <Drive>* plistDrives * \param pointer of list <Drive>* plistDrives
@ -454,11 +521,12 @@ void reHDD::handleArrowKey(TUI::UserInput userInput)
break; break;
} }
Logger::logThis()->info("ArrowKey - selected drive: " + to_string(u8SelectedEntry)); //Logger::logThis()->info("ArrowKey - selected drive: " + to_string(u8SelectedEntry));
} }
void reHDD::handleEnter() void reHDD::handleEnter()
{ {
if (getSelectedDrive() != nullptr) if (getSelectedDrive() != nullptr)
{ {
if(getSelectedDrive()->state == Drive::TaskState::SHRED_SELECTED) if(getSelectedDrive()->state == Drive::TaskState::SHRED_SELECTED)
@ -466,7 +534,8 @@ void reHDD::handleEnter()
Logger::logThis()->info("Started shred for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial()); Logger::logThis()->info("Started shred for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial());
getSelectedDrive()->state = Drive::TaskState::SHRED_ACTIVE; getSelectedDrive()->state = Drive::TaskState::SHRED_ACTIVE;
//task for drive is running --> don´t show more task options //task for drive is running --> don´t show more task options
thread(ThreadShred).detach(); Drive* pTmpDrive = getSelectedDrive();
thread(ThreadShred, pTmpDrive).detach();
} }
if(getSelectedDrive()->state == Drive::TaskState::DELETE_SELECTED) if(getSelectedDrive()->state == Drive::TaskState::DELETE_SELECTED)

View File

@ -2,11 +2,19 @@
* @file shred.cpp * @file shred.cpp
* @brief shred drive * @brief shred drive
* @author hendrik schutter * @author hendrik schutter
* @date 03.05.2020 * @date 22.08.2022
*/ */
#include "../include/reHDD.h" #include "../include/reHDD.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "../tfnoisegen/tfprng.h"
#ifdef __cplusplus
}
#endif
const static char *randomsrc = (char*) "/dev/urandom"; const static char *randomsrc = (char*) "/dev/urandom";
Shred::Shred() Shred::Shred()
@ -24,6 +32,9 @@ Shred::~Shred()
*/ */
int Shred::shredDrive(Drive* drive, int* ipSignalFd) int Shred::shredDrive(Drive* drive, int* ipSignalFd)
{ {
ostringstream address;
address << (void const *)&(*drive);
Logger::logThis()->info("Shred-Task started - Drive: " + drive->getModelName() + "-" + drive->getSerial() + " @" + address.str());
#ifdef DRYRUN #ifdef DRYRUN
for(int i = 0; i<=500; i++) for(int i = 0; i<=500; i++)
@ -40,6 +51,7 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
#ifndef DRYRUN #ifndef DRYRUN
const char *cpDrivePath = drive->getPath().c_str(); const char *cpDrivePath = drive->getPath().c_str();
unsigned char ucKey[TFNG_KEY_SIZE];
//open random source //open random source
randomSrcFileDiscr = open(randomsrc, O_RDONLY | O_LARGEFILE); randomSrcFileDiscr = open(randomsrc, O_RDONLY | O_LARGEFILE);
@ -63,7 +75,22 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
return -1; return -1;
} }
//read key for random generator
ssize_t readRet = read(randomSrcFileDiscr, ucKey, sizeof(ucKey)) ;
if (readRet <= 0)
{
std::string errorMsg(strerror(readRet));
Logger::logThis()->error("Shred-Task: Read random key failed! " + errorMsg + " - Drive: " + drive->getSerial());
perror(randomsrc);
cleanup();
return -1;
}
tfng_prng_seedkey(ucKey);
this->ulDriveByteSize = getDriveSizeInBytes(driveFileDiscr); this->ulDriveByteSize = getDriveSizeInBytes(driveFileDiscr);
drive->sShredSpeed.chronoShredTimestamp = std::chrono::system_clock::now();; //set inital timestamp for speed metric
drive->sShredSpeed.ulSpeedMetricBytesWritten = 0U; //uses to calculate speed metric
#ifdef LOG_LEVEL_HIGH #ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("Shred-Task: Bytes-Size of Drive: " + to_string(this->ulDriveByteSize) + " - Drive: " + drive->getSerial()); Logger::logThis()->info("Shred-Task: Bytes-Size of Drive: " + to_string(this->ulDriveByteSize) + " - Drive: " + drive->getSerial());
@ -72,44 +99,21 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
for (unsigned int uiShredIterationCounter = 0U; uiShredIterationCounter < SHRED_ITERATIONS; uiShredIterationCounter++) for (unsigned int uiShredIterationCounter = 0U; uiShredIterationCounter < SHRED_ITERATIONS; uiShredIterationCounter++)
{ {
unsigned long ulDriveByteCounter = 0U; //used for one shred-iteration to keep track of the current drive position unsigned long ulDriveByteCounter = 0U; //used for one shred-iteration to keep track of the current drive position
uint32_t u32ChunkDimensionIndex = 0U;
if(uiShredIterationCounter == (SHRED_ITERATIONS-1)) if(uiShredIterationCounter == (SHRED_ITERATIONS-1))
{ {
//last shred iteration --> overwrite with zeros instead with random data //last shred iteration --> overwrite (just the write chunk) bytes with zeros instead with random data
memset(caChunk, 0U, CHUNK_DIMENSION*CHUNK_SIZE); memset(caTfngData, 0U, CHUNK_SIZE);
} }
while (ulDriveByteCounter < ulDriveByteSize) while (ulDriveByteCounter < ulDriveByteSize)
{ {
int iBytesToShred = 0; //Bytes that will be overwritten in this chunk-iteration int iBytesToShred = 0; //Bytes that will be overwritten in this chunk-iteration
if((u32ChunkDimensionIndex == 0U) && (uiShredIterationCounter != (SHRED_ITERATIONS-1))) if(uiShredIterationCounter != (SHRED_ITERATIONS-1))
{ {
//read new chunks from random source if needed and this is NOT the last shred iteration //NOT last shred iteration --> generate new random data
unsigned long ulBytesInChunkBuffer = 0U; tfng_prng_genrandom(caTfngData, TFNG_DATA_SIZE);
while (ulBytesInChunkBuffer < CHUNK_DIMENSION*CHUNK_SIZE)
{
//read new random bytes
int iReadBytes = read(randomSrcFileDiscr, caChunk, ((CHUNK_DIMENSION*CHUNK_SIZE)-ulBytesInChunkBuffer));
if (iReadBytes > 0)
{
ulBytesInChunkBuffer += iReadBytes;
}
else
{
std::string errorMsg(strerror(iReadBytes));
Logger::logThis()->error("Shred-Task: Read from random source failed! " + errorMsg + " - Drive: " + drive->getSerial());
perror("unable to read random data");
cleanup();
return -1;;
}
} //end chunk read
#ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("Shred-Task: Read new random data - Drive: " + drive->getSerial());
#endif
} }
if((ulDriveByteSize-ulDriveByteCounter) < CHUNK_SIZE) if((ulDriveByteSize-ulDriveByteCounter) < CHUNK_SIZE)
@ -121,7 +125,7 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
iBytesToShred = CHUNK_SIZE; iBytesToShred = CHUNK_SIZE;
} }
int iByteShredded = write(driveFileDiscr, caChunk[u32ChunkDimensionIndex], iBytesToShred); int iByteShredded = write(driveFileDiscr, caTfngData, iBytesToShred);
if(iByteShredded <= 0) if(iByteShredded <= 0)
{ {
@ -132,18 +136,20 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
return -1; return -1;
} }
u32ChunkDimensionIndex = (u32ChunkDimensionIndex+1)%CHUNK_DIMENSION;
ulDriveByteCounter += iByteShredded; ulDriveByteCounter += iByteShredded;
ulDriveByteOverallCount += iByteShredded; ulDriveByteOverallCount += iByteShredded;
d32Percent = this->calcProgress(); d32Percent = this->calcProgress();
drive->sShredSpeed.ulSpeedMetricBytesWritten += iByteShredded;
#ifdef LOG_LEVEL_HIGH #ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("Shred-Task: ByteCount: " + to_string(ulDriveByteCounter) + " - iteration: " + to_string((uiShredIterationCounter+1)) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial()); Logger::logThis()->info("Shred-Task: ByteCount: " + to_string(ulDriveByteCounter) + " - iteration: " + to_string((uiShredIterationCounter+1)) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial());
#endif #endif
if((d32Percent-d32TmpPercent) >= 0.01) if((d32Percent-d32TmpPercent) >= 0.01)
{ {
//set shred percantage
drive->setTaskPercentage(d32TmpPercent); drive->setTaskPercentage(d32TmpPercent);
d32TmpPercent = d32Percent; d32TmpPercent = d32Percent;
//signal process in shreding
write(*ipSignalFd, "A",1); write(*ipSignalFd, "A",1);
} }
@ -157,13 +163,19 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd)
cleanup(); cleanup();
return -1; return -1;
} }
}//end one chunk write //end one chunk write
}
if(0 != iRewindDrive(driveFileDiscr)) if(0 != iRewindDrive(driveFileDiscr))
{ {
Logger::logThis()->error("Shred-Task: Unable to rewind drive! - Drive: " + drive->getSerial());
cleanup(); cleanup();
return -1; return -1;
} }
} //end one shred iteration //end one shred iteration
}
//end of all shred iteratio
tfng_prng_seedkey(NULL); //reset random generator
#ifdef ZERO_CHECK_ALERT #ifdef ZERO_CHECK_ALERT
drive->u32DriveChecksumAferShredding = uiCalcChecksum(driveFileDiscr, drive, ipSignalFd); drive->u32DriveChecksumAferShredding = uiCalcChecksum(driveFileDiscr, drive, ipSignalFd);
@ -250,18 +262,19 @@ unsigned int Shred::uiCalcChecksum(fileDescriptor file,Drive* drive, int* ipSign
{ {
iBytesToCheck = CHUNK_SIZE; iBytesToCheck = CHUNK_SIZE;
} }
int iReadBytes = read(file, caChunk, iBytesToCheck); int iReadBytes = read(file, caReadBuffer, iBytesToCheck);
for (int iReadBytesCounter = 0U; iReadBytesCounter < iReadBytes; iReadBytesCounter++) for (int iReadBytesCounter = 0U; iReadBytesCounter < iReadBytes; iReadBytesCounter++)
{ {
uiChecksum += caChunk[0][iReadBytesCounter]; uiChecksum += caReadBuffer[iReadBytesCounter];
} }
ulDriveByteCounter += iReadBytes; ulDriveByteCounter += iReadBytes;
ulDriveByteOverallCount += iReadBytes; ulDriveByteOverallCount += iReadBytes;
d32Percent = this->calcProgress(); d32Percent = this->calcProgress();
drive->sShredSpeed.ulSpeedMetricBytesWritten += iReadBytes;
#ifdef LOG_LEVEL_HIGH #ifdef LOG_LEVEL_HIGH
Logger::logThis()->info("Shred-Task (Checksum): ByteCount: " + to_string(ulDriveByteCounter) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial()); Logger::logThis()->info("Shred-Task (Checksum): ByteCount: " + to_string(ulDriveByteCounter) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial());
#endif #endif
if((d32Percent-d32TmpPercent) >= 0.9) if((d32Percent-d32TmpPercent) >= 0.01)
{ {
drive->setTaskPercentage(d32TmpPercent); drive->setTaskPercentage(d32TmpPercent);
d32TmpPercent = d32Percent; d32TmpPercent = d32Percent;
@ -274,5 +287,5 @@ unsigned int Shred::uiCalcChecksum(fileDescriptor file,Drive* drive, int* ipSign
void Shred::cleanup() void Shred::cleanup()
{ {
close(driveFileDiscr); close(driveFileDiscr);
close( randomSrcFileDiscr); close(randomSrcFileDiscr);
} }

View File

@ -14,6 +14,7 @@ uint64_t SMART::capacity = 0U;
uint32_t SMART::errorCount = 0U; uint32_t SMART::errorCount = 0U;
uint32_t SMART::powerOnHours = 0U; uint32_t SMART::powerOnHours = 0U;
uint32_t SMART::powerCycle = 0U; uint32_t SMART::powerCycle = 0U;
uint32_t SMART::temperature = 0U;
/** /**
* \brief get and set S.M.A.R.T. values in Drive * \brief get and set S.M.A.R.T. values in Drive
@ -29,6 +30,7 @@ void SMART::readSMARTData(Drive* drive)
errorCount = 0U; errorCount = 0U;
powerOnHours = 0U; powerOnHours = 0U;
powerCycle = 0U; powerCycle = 0U;
temperature = 0U;
size_t len = 0; //lenght of found line size_t len = 0; //lenght of found line
char* cLine = NULL; //found line char* cLine = NULL; //found line
@ -50,9 +52,10 @@ void SMART::readSMARTData(Drive* drive)
SMART::parseErrorCount(sLine); SMART::parseErrorCount(sLine);
SMART::parsePowerOnHours(sLine); SMART::parsePowerOnHours(sLine);
SMART::parsePowerCycle(sLine); SMART::parsePowerCycle(sLine);
SMART::parseTemperature(sLine);
} }
pclose(outputfileSmart); pclose(outputfileSmart);
drive->setDriveSMARTData(modelFamily, modelName, serial, capacity, errorCount, powerOnHours, powerCycle); //wirte data in drive drive->setDriveSMARTData(modelFamily, modelName, serial, capacity, errorCount, powerOnHours, powerCycle, temperature); //wirte data in drive
} }
/** /**
@ -176,3 +179,26 @@ void SMART::parsePowerCycle(string sLine)
} }
} }
/**
* \brief parse temperature
* \param string output line of smartctl
* \return void
*/
void SMART::parseTemperature(string sLine)
{
string search("\"current\": ");
size_t found = sLine.find(search);
if (found!=string::npos)
{
sLine.erase(0, sLine.find(": ") + 2);
sLine.erase(sLine.length()-1, 2);
if(sLine == "{")
{
temperature = 0U; // this drive doesn't support temperatur
}
else
{
temperature = stol(sLine);
}
}
}

View File

@ -74,11 +74,12 @@ void TUI::updateTUI(list <Drive>* plistDrives, uint8_t u8SelectedEntry)
for (it = plistDrives->begin(); it != plistDrives->end(); ++it) for (it = plistDrives->begin(); it != plistDrives->end(); ++it)
{ {
string sModelFamily = it->getModelFamily(); string sModelFamily = it->getModelFamily();
string sModelName = it->getModelName(); string sSerial = "SN: " + it->getSerial();
string sCapacity = it->sCapacityToText(); string sCapacity = it->sCapacityToText();
string sState = " "; string sState = " ";
string sSpeed = " ";
string sTime = " "; string sTime = " ";
string sTemp = it->sTemperatureToText();
bool bSelectedEntry = false; bool bSelectedEntry = false;
@ -87,17 +88,16 @@ void TUI::updateTUI(list <Drive>* plistDrives, uint8_t u8SelectedEntry)
bSelectedEntry = true; //mark this drive in entries list bSelectedEntry = true; //mark this drive in entries list
displaySelectedDrive(*it, u16StdscrX, u16StdscrY); displaySelectedDrive(*it, u16StdscrX, u16StdscrY);
if((it->getPowerOnHours() >= WORSE_HOURS) || (it->getPowerCycles() >= WORSE_POWERUP) || (it->getErrorCount() > 0)) if((it->getPowerOnHours() >= WORSE_HOURS) || (it->getPowerCycles() >= WORSE_POWERUP) || (it->getErrorCount() > 0) || (it->getTemperature() >= WORSE_TEMPERATURE))
{ {
// smart values are bad --> show warning // smart values are bad --> show warning
smartWarning=createSmartWarning(50, 10, ((u16StdscrX)-(int)(u16StdscrX/2)+35),(int)(u16StdscrY/2)-5, it->getPath(), it->getPowerOnHours(), it->getPowerCycles(), it->getErrorCount()); smartWarning=createSmartWarning(50, 10, ((u16StdscrX)-(int)(u16StdscrX/2)+35),(int)(u16StdscrY/2)-5, it->getPath(), it->getPowerOnHours(), it->getPowerCycles(), it->getErrorCount(), it->getTemperature());
wrefresh(smartWarning); wrefresh(smartWarning);
} }
} }
stringstream stream; stringstream stream;
switch (it->state) switch (it->state)
{ {
case Drive::SHRED_ACTIVE: case Drive::SHRED_ACTIVE:
@ -107,6 +107,7 @@ void TUI::updateTUI(list <Drive>* plistDrives, uint8_t u8SelectedEntry)
it->calculateTaskDuration(); it->calculateTaskDuration();
sTime = this->formatTimeDuration(it->getTaskDuration()); sTime = this->formatTimeDuration(it->getTaskDuration());
sSpeed = this->formatSpeed(it->sShredSpeed.u32ShredTimeDelta, it->sShredSpeed.ulWrittenBytes);
break; break;
case Drive::DELETE_ACTIVE: case Drive::DELETE_ACTIVE:
sState = "Deleting ..."; sState = "Deleting ...";
@ -151,7 +152,7 @@ void TUI::updateTUI(list <Drive>* plistDrives, uint8_t u8SelectedEntry)
break; break;
} }
WINDOW * tmp = createEntryWindow( ((int)(u16StdscrX/3) - 2), 5, 3, (5* (u8Index) )+3, sModelFamily, sModelName, sCapacity, sState, sTime, bSelectedEntry); WINDOW * tmp = createEntryWindow( ((int)(u16StdscrX/3) - 2), 5, 3, (5* (u8Index) )+3, (distance(plistDrives->begin(), it)+1), sModelFamily, sSerial, sCapacity, sState, sTime, sSpeed, sTemp, bSelectedEntry);
wrefresh(tmp); wrefresh(tmp);
u8Index++; u8Index++;
}//end loop though drives }//end loop though drives
@ -203,6 +204,9 @@ enum TUI::UserInput TUI::readUserInput()
case 's': case 's':
return TUI::UserInput::Shred; return TUI::UserInput::Shred;
break; break;
case 'S':
return TUI::UserInput::ShredAll;
break;
default: default:
return TUI::UserInput::Undefined; return TUI::UserInput::Undefined;
break; break;
@ -305,7 +309,7 @@ WINDOW* TUI::overwriteDetailViewWindow( int iXSize, int iYSize, int iXStart)
return newWindow; return newWindow;
} }
WINDOW* TUI::createEntryWindow(int iXSize, int iYSize, int iXStart, int iYStart, string sModelFamily, string sModelName, string sCapacity, string sState, string sTime, bool bSelected) WINDOW* TUI::createEntryWindow(int iXSize, int iYSize, int iXStart, int iYStart, int iListIndex, string sModelFamily, string sSerial, string sCapacity, string sState, string sTime, string sSpeed, string sTemp, bool bSelected)
{ {
WINDOW *newWindow; WINDOW *newWindow;
newWindow = newwin(iYSize, iXSize, iYStart, iXStart); newWindow = newwin(iYSize, iXSize, iYStart, iXStart);
@ -325,12 +329,16 @@ WINDOW* TUI::createEntryWindow(int iXSize, int iYSize, int iXStart, int iYStart,
box(newWindow, ACS_VLINE, ACS_HLINE); box(newWindow, ACS_VLINE, ACS_HLINE);
mvwaddstr(newWindow,1, 1, sModelFamily.c_str()); mvwaddstr(newWindow,1, 1, to_string(iListIndex).c_str());
mvwaddstr(newWindow,2, 1, sModelName.c_str());
mvwaddstr(newWindow,3, 1, sCapacity.c_str());
mvwaddstr(newWindow,1, 5, sModelFamily.c_str());
mvwaddstr(newWindow,2, 5, sSerial.c_str());
mvwaddstr(newWindow,3, 5, sCapacity.c_str());
mvwaddstr(newWindow,3, 5+sCapacity.length()+3, sTemp.c_str());
mvwaddstr(newWindow,1, iXSize-sSpeed.length()-5, sSpeed.c_str());
mvwaddstr(newWindow,2, iXSize-sState.length()-5, sState.c_str()); mvwaddstr(newWindow,2, iXSize-sState.length()-5, sState.c_str());
mvwaddstr(newWindow,3, iXSize-sState.length()-5, sTime.c_str()); mvwaddstr(newWindow,3, iXSize-sTime.length()-5, sTime.c_str());
return newWindow; return newWindow;
} }
@ -353,10 +361,14 @@ WINDOW* TUI::createSystemStats(int iXSize, int iYSize, int iXStart, int iYStart)
strftime(buffer,sizeof(buffer),"Date: %d-%m-%Y Time: %H:%M",timeinfo); strftime(buffer,sizeof(buffer),"Date: %d-%m-%Y Time: %H:%M",timeinfo);
string time(buffer); string time(buffer);
string sLine01 = "reHDD - hard drive refurbishing tool"; string sLine01 = "reHDD - hard drive refurbishing tool";
string sLine02 = "Version: " + string(REHDD_VERSION); string sLine02 = "Version: " + string(REHDD_VERSION);
string sLine03 = "Available under GPL 3.0"; string sLine03 = "Build time: ";
string sLine04 = "https://git.mosad.xyz/localhorst/reHDD"; sLine03.append(__DATE__);
sLine03.append(" ");
sLine03.append(__TIME__);
string sLine04 = "Available under GPL 3.0";
string sLine05 = "https://git.mosad.xyz/localhorst/reHDD";
uint16_t u16Line = 2; uint16_t u16Line = 2;
@ -364,6 +376,7 @@ WINDOW* TUI::createSystemStats(int iXSize, int iYSize, int iXStart, int iYStart)
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine02.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine02.c_str());
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine03.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine03.c_str());
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine04.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine04.c_str());
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLine05.c_str());
u16Line++; u16Line++;
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), time.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), time.c_str());
@ -384,19 +397,19 @@ WINDOW* TUI::createMenuView(int iXSize, int iYSize, int iXStart, int iYStart, st
if(menustate.bAbort) if(menustate.bAbort)
{ {
string sLineTmp = "Press A for Abort"; string sLineTmp = "Press a for Abort";
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str());
u16Line++; u16Line++;
} }
if(menustate.bShred) if(menustate.bShred)
{ {
string sLineTmp = "Press S for Shred "; string sLineTmp = "Press s for Shred (S for all drives)";
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str());
u16Line++; u16Line++;
} }
if(menustate.bDelete) if(menustate.bDelete)
{ {
string sLineTmp = "Press D for Delete"; string sLineTmp = "Press d for Delete";
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLineTmp.size()/2), sLineTmp.c_str());
} }
@ -506,6 +519,17 @@ string TUI::formatTimeDuration(time_t u32Duration)
return out.str(); return out.str();
} }
string TUI::formatSpeed(time_t u32ShredTimeDelta, unsigned long ulWrittenBytes)
{
std::ostringstream out;
double dDeltaSec = ((double)((u32ShredTimeDelta)/1000000000.0)); //convert nano in sec
double speed = ((ulWrittenBytes/1000000.0)/dDeltaSec);
char s[25];
sprintf(s, "%0.2lf MB/s", speed);
out << s;
return out.str();
}
void TUI::displaySelectedDrive(Drive drive, int stdscrX, int stdscrY) void TUI::displaySelectedDrive(Drive drive, int stdscrX, int stdscrY)
{ {
struct MenuState menustate; struct MenuState menustate;
@ -563,7 +587,7 @@ void TUI::displaySelectedDrive(Drive drive, int stdscrX, int stdscrY)
} }
} }
WINDOW* TUI::createSmartWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, uint32_t u32PowerOnHours, uint32_t u32PowerCycles, uint32_t u32ErrorCount) WINDOW* TUI::createSmartWarning(int iXSize, int iYSize, int iXStart, int iYStart, string sPath, uint32_t u32PowerOnHours, uint32_t u32PowerCycles, uint32_t u32ErrorCount, uint32_t u32Temperature)
{ {
WINDOW *newWindow; WINDOW *newWindow;
newWindow = newwin(iYSize, iXSize, iYStart, iXStart); newWindow = newwin(iYSize, iXSize, iYStart, iXStart);
@ -598,6 +622,13 @@ WINDOW* TUI::createSmartWarning(int iXSize, int iYSize, int iXStart, int iYStart
{ {
string sLineTmp = "S.M.A.R.T. erros detected: " + to_string(u32ErrorCount); string sLineTmp = "S.M.A.R.T. erros detected: " + to_string(u32ErrorCount);
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLineTmp.c_str()); mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLineTmp.c_str());
u16Line++;
}
if(u32Temperature >= WORSE_TEMPERATURE)
{
string sLineTmp = "Drive too hot: " + to_string(u32Temperature)+" C";
mvwaddstr(newWindow,u16Line++, (iXSize/2)-(sLine01.size()/2), sLineTmp.c_str());
} }
return newWindow; return newWindow;
} }

1
tfnoisegen Submodule

@ -0,0 +1 @@
Subproject commit 488716ef22ac5a1aae235a59bea2997ac7e8e45a