38 Commits

Author SHA1 Message Date
573a0df080 Merge pull request 'version 0.3.0' (#52) from develop into master
Reviewed-on: #52
2022-09-20 21:56:04 +02:00
1f50f87f97 update version and readme 2022-09-20 21:53:43 +02:00
17cc41dc5f display human readable timestamp 2022-08-25 12:07:57 +02:00
02c9ab99f7 display human readable timestamp 2022-08-25 12:07:18 +02:00
7d69096df3 Revert "decrease shred iterations"
This reverts commit 7dfa805044.
2022-08-25 09:18:12 +02:00
1b9fa348d3 display software build time 2022-08-24 16:35:12 +02:00
a347bf433c display temperature alert if drive too hot 2022-08-24 16:27:51 +02:00
69fd10207d copy newer S.M.A.R.T. values to existing drive 2022-08-24 16:11:36 +02:00
2df5ceb0c8 read temperature via S.M.A.R.T and display 2022-08-24 16:00:18 +02:00
7dfa805044 decrease shred iterations 2022-08-24 14:27:43 +02:00
bb69a59794 fix frozen and metric for checking iteration 2022-08-23 23:20:50 +02:00
a656d0a9f4 UI: display drive count with index 2022-08-23 00:03:45 +02:00
50bd896cb9 display SN in overview for entry 2022-08-22 23:42:20 +02:00
3ee59d8c58 Merge pull request 'speedup shred' (#46) from speedup into develop
Reviewed-on: #46
2022-08-22 23:34:15 +02:00
d92448aa97 optimal chunk size 2022-08-22 23:09:41 +02:00
edcf680b95 update shred metric in main thread instead of shred thread 2022-08-22 18:35:27 +02:00
09446b52ca using tfng instead of urandom 2022-08-22 15:27:29 +02:00
4cf1efea7a updated readme for submodules 2022-08-22 14:36:52 +02:00
f0f1e4fd93 remove false git submodule 2022-08-22 14:27:42 +02:00
d7aaa9647d added Threefish cipher as submodule 2022-08-22 14:24:31 +02:00
4862a45ef6 remove unnecessary mutesx 2022-08-21 16:24:55 +02:00
70f5727eb3 protect lists with mutex 2022-08-21 15:52:47 +02:00
b6f0c5e89f fix missing include 2022-08-20 16:11:48 +02:00
e3aefb24ee added feature to start shredding for all drives 2022-08-20 16:09:40 +02:00
9863c5591e cal metric: shred speed 2022-06-30 00:32:13 +02:00
c61859ed4e added shred speed to TUI 2022-06-29 19:27:37 +02:00
8de45505e4 fix update script 2022-06-29 19:08:43 +02:00
f8ba9c6732 Merge branch 'master' into develop 2022-05-18 22:03:14 +02:00
c01797be7f Merge branch 'develop' 2022-05-18 22:02:47 +02:00
0684744bdb update docs 2022-05-17 09:16:58 +02:00
8c54e0e7d9 updated REDME 2022-01-26 19:38:16 +01:00
46a2de7bc4 Merge pull request 'change drive filter for system drive' (#36) from develop into master
Reviewed-on: #36
2022-01-26 19:34:37 +01:00
52f5597ba9 updated service 2022-01-26 17:32:21 +01:00
9b9806b5c2 „README.md“ ändern 2022-01-26 17:18:12 +01:00
1e455bde02 added curl 2022-01-26 16:52:45 +01:00
8034ac496b Merge pull request 'adopt newer debian' (#35) from develop into master
Reviewed-on: #35
2022-01-26 16:41:56 +01:00
354ee04e73 „README.md“ ändern 2022-01-26 16:40:20 +01:00
45a5cb303b upload log to dev 2020-10-01 17:52:46 +02:00
21 changed files with 359 additions and 210 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 htop sudo`
* `apt-get install hwinfo smartmontools curl`
### 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`
@ -43,3 +50,7 @@ Get the first 8 Bytes from your UUID via `blkid /dev/sdX`
`reboot` `reboot`
## Build docs
`make docs`
open `doc/html/index.html` in browser

View File

@ -467,7 +467,7 @@ LOOKUP_CACHE_SIZE = 0
# normally produced when WARNINGS is set to YES. # normally produced when WARNINGS is set to YES.
# The default value is: NO. # The default value is: NO.
EXTRACT_ALL = NO EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation. # be included in the documentation.
@ -904,7 +904,7 @@ FILE_PATTERNS = *.c \
# be searched for input files as well. # be searched for input files as well.
# The default value is: NO. # The default value is: NO.
RECURSIVE = NO RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be # The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a # excluded from the INPUT source files. This way you can easily exclude a
@ -1493,7 +1493,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag # structure should be generated to display hierarchical information. If the tag
@ -1510,7 +1510,7 @@ DISABLE_INDEX = NO
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation. # doxygen will group on one line in the generated HTML documentation.
@ -2260,7 +2260,7 @@ HIDE_UNDOC_RELATIONS = YES
# set to NO # set to NO
# The default value is: NO. # The default value is: NO.
HAVE_DOT = NO HAVE_DOT = YES
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of # to run in parallel. When set to 0 doxygen will base this on the number of
@ -2326,7 +2326,7 @@ GROUP_GRAPHS = YES
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO UML_LOOK = YES
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the # If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may # class node. If there are many fields or methods and many nodes the graph may
@ -2377,7 +2377,7 @@ INCLUDED_BY_GRAPH = YES
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO CALL_GRAPH = YES
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method. # dependency graph for every global function or class method.
@ -2389,7 +2389,7 @@ CALL_GRAPH = NO
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO CALLER_GRAPH = YES
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one. # hierarchy of all classes instead of a textual one.

View File

@ -1,60 +0,0 @@
# Installation
**[1]** In terminal als root einloggen\
**[2]** In reHDD_prototype wechseln\
**[3]** Abhängigkeiten installieren\
`apt-get install smartmontools`\
`apt-get install hwinfo`\
`apt-get install util-linux`
**[4]** reHDD ausführbar machen\
`chmod +x reHDD`\
**[5]** ignoreDrives.conf bearbeiten
##### Ein Eintrag in der ignoreDrives-Datei sorgt dafür das die Software bestimmte Festplatten ignoriert. Dies ist wichtig damit nicht unbeabsichtigt die Systemfestplatte oder weitere Festplatten bearbeitet (gelöscht) werden.
Beispiel Inhalt:
```
/dev/sda:508eff7d-f039-4efb-9e2c-22dffdfdfdfd
/dev/sdb:07dfffff-c4b6-46e7-9cdf-3cfdfdffd53d
/dev/sdc:dfff974d-1af2-4dfd-9dfd-a2d8e4c43dff
```
Ein Eintrag setzt sich aus zwei Teilen zusammen:
**[Pfad]:[PARTUUID]**
Der Pfad kann mittels `fdisk -l` ermittelt werden.\
Die PARTUUID kann mittels `blkid /dev/sda` ermittelt werden, wobei `/dev/sda` derzuvor ermittelte Pfad ist.
# Benutzung
reHDD starten mit `./reHDD` (Wichtig ist das reHDD mit root-Rechen ausgeführt wird, entwender als root einloggen oder mit `sudo`)
reHDD sucht automatisch nach allen verfügbaren Festplatten und filtert die zu ignorierenden heraus.\
Für die verbleibenden Festplatten wird eine Übersicht ausgegeben.
Der Nutzer wird gefragt, welche Festplatte bearbeitet werden soll und gibt die Nummer ein.
Beispiel:
```
hostname@hendrik:/reHDD_prototype # ./reHDD
refurbishingHddTool
created app
app logic
search drives ...
------------DRIVES---------------
Drive: 0
Path: /dev/sdd
ModelFamily:
ModelName: ADATA SU650
Capacity: 120034123776
Serial: H50125K001601
PowerOnHours: 93
PowerCycle: 187
ErrorCount: 0
---------------------------------
Select drive to wipe:
0
Selected drive index: 0
wipe: shred -v /dev/sdd
shred: /dev/sdd: Durchgang 1/3 (random)…
shred: /dev/sdd: Durchgang 1/3 (random)…847MiB/112GiB 0%
...
```

View File

@ -1,26 +0,0 @@
#! /usr/bin/bash
echo starting update
FILE=./ignoreDrives.conf
if test -f "$FILE"; then
echo backup exits
else
cp reHDD/ignoreDrives.conf ./ignoreDrives.conf
fi
cd reHDD
git reset
git stash force
git stash
git checkout master
git pull
make release
cp ../ignoreDrives.conf ./

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,6 +37,13 @@ public:
private: private:
string sPath; string sPath;
time_t u32Timestamp = 0U; //unix timestamp for detecting a frozen drive
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
struct
{
string sModelFamily; string sModelFamily;
string sModelName; string sModelName;
string sSerial; string sSerial;
@ -36,10 +51,8 @@ private:
uint32_t u32ErrorCount = 0U; uint32_t u32ErrorCount = 0U;
uint32_t u32PowerOnHours = 0U; //in hours uint32_t u32PowerOnHours = 0U; //in hours
uint32_t u32PowerCycles = 0U; uint32_t u32PowerCycles = 0U;
time_t u32Timestamp = 0U; //unix timestamp for detecting a frozen drive uint32_t u32Temperature = 0U; //in Fahrenheit, just kidding: degree Celsius
double d32TaskPercentage = 0U; //in percent for Shred (1 to 100) } sSmartData;
time_t u32TimestampTaskStart = 0U; //unix timestamp for duration of an action
time_t u32TaskDuration = 0U; //time needed to complete the task
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 startShredAllDrives(list <Drive>* plistDrives);
static void updateShredMetrics(list <Drive>* plistDrives);
static void filterIgnoredDrives(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

@ -4,7 +4,7 @@ Description=dmesg on tty2
[Service] [Service]
WorkingDirectory=/usr/bin/ WorkingDirectory=/usr/bin/
ExecStart= ExecStart=
ExecStart=-/usr/bin/dmesg -wH ExecStart=-/usr/bin/dmesg -wHT
StandardInput=tty StandardInput=tty
StandardOutput=tty StandardOutput=tty
Restart=always Restart=always

30
scripts/update.sh Normal file
View File

@ -0,0 +1,30 @@
#! /usr/bin/bash
echo starting update
systemctl stop /lib/systemd/system/getty@tty1.service.d
cd /root/reHDD/
FILE=./ignoreDrives.conf
if test -f "$FILE"; then
echo backup exits
else
cp /root/reHDD/ignoreDrives.conf /root/ignoreDrives.conf
fi
git reset
git stash force
git stash
git checkout master
git pull
make release
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;
} }
@ -355,8 +363,12 @@ WINDOW* TUI::createSystemStats(int iXSize, int iYSize, int iXStart, int iYStart)
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

Submodule tfnoisegen added at 488716ef22