2022-05-14 14:06:16 +02:00
/**
* @ file shred . cpp
* @ brief shred drive
* @ author hendrik schutter
2022-08-22 15:27:29 +02:00
* @ date 22.08 .2022
2022-05-14 14:06:16 +02:00
*/
# include "../include/reHDD.h"
2022-08-22 14:24:31 +02:00
# ifdef __cplusplus
extern " C " {
# endif
# include "../tfnoisegen/tfprng.h"
# ifdef __cplusplus
}
# endif
2022-05-14 14:06:16 +02:00
const static char * randomsrc = ( char * ) " /dev/urandom " ;
Shred : : Shred ( )
{
}
Shred : : ~ Shred ( )
{
}
/**
* \ brief shred drive with shred
* \ param pointer of Drive instance
* \ return void
*/
int Shred : : shredDrive ( Drive * drive , int * ipSignalFd )
{
2022-08-21 15:52:47 +02:00
ostringstream address ;
address < < ( void const * ) & ( * drive ) ;
Logger : : logThis ( ) - > info ( " Shred-Task started - Drive: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) + " @ " + address . str ( ) ) ;
2022-05-14 14:06:16 +02:00
# ifdef DRYRUN
for ( int i = 0 ; i < = 500 ; i + + )
{
if ( drive - > state ! = Drive : : SHRED_ACTIVE )
{
2022-05-15 15:17:49 +02:00
return 0 ;
2022-05-14 14:06:16 +02:00
}
drive - > setTaskPercentage ( i + 0.05 ) ;
write ( * ipSignalFd , " A " , 1 ) ;
usleep ( 20000 ) ;
}
# endif
# ifndef DRYRUN
const char * cpDrivePath = drive - > getPath ( ) . c_str ( ) ;
2022-08-22 15:27:29 +02:00
unsigned char ucKey [ TFNG_KEY_SIZE ] ;
2022-05-14 14:06:16 +02:00
//open random source
randomSrcFileDiscr = open ( randomsrc , O_RDONLY | O_LARGEFILE ) ;
if ( randomSrcFileDiscr = = - 1 )
{
2022-05-15 15:17:49 +02:00
std : : string errorMsg ( strerror ( randomSrcFileDiscr ) ) ;
Logger : : logThis ( ) - > error ( " Shred-Task: Open random source failed! " + errorMsg + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
perror ( randomsrc ) ;
cleanup ( ) ;
return - 1 ;
}
//open disk
driveFileDiscr = open ( cpDrivePath , O_RDWR | O_LARGEFILE ) ;
if ( driveFileDiscr = = - 1 )
{
2022-05-15 15:17:49 +02:00
std : : string errorMsg ( strerror ( driveFileDiscr ) ) ;
Logger : : logThis ( ) - > error ( " Shred-Task: Open drive failed! " + errorMsg + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
perror ( cpDrivePath ) ;
cleanup ( ) ;
return - 1 ;
}
2022-08-22 15:27:29 +02:00
//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 ) ;
2022-05-14 14:06:16 +02:00
this - > ulDriveByteSize = getDriveSizeInBytes ( driveFileDiscr ) ;
2022-06-30 00:32:13 +02:00
drive - > sShredSpeed . chronoShredTimestamp = std : : chrono : : system_clock : : now ( ) ; ; //set inital timestamp for speed metric
2022-08-22 18:35:27 +02:00
drive - > sShredSpeed . ulSpeedMetricBytesWritten = 0U ; //uses to calculate speed metric
2022-05-14 14:06:16 +02:00
# ifdef LOG_LEVEL_HIGH
Logger : : logThis ( ) - > info ( " Shred-Task: Bytes-Size of Drive: " + to_string ( this - > ulDriveByteSize ) + " - Drive: " + drive - > getSerial ( ) ) ;
# endif
for ( unsigned int uiShredIterationCounter = 0U ; uiShredIterationCounter < SHRED_ITERATIONS ; uiShredIterationCounter + + )
{
2022-05-15 15:17:49 +02:00
unsigned long ulDriveByteCounter = 0U ; //used for one shred-iteration to keep track of the current drive position
2022-05-14 14:06:16 +02:00
if ( uiShredIterationCounter = = ( SHRED_ITERATIONS - 1 ) )
{
2022-08-22 15:27:29 +02:00
//last shred iteration --> overwrite (just the write chunk) bytes with zeros instead with random data
memset ( caTfngData , 0U , CHUNK_SIZE ) ;
2022-05-14 14:06:16 +02:00
}
while ( ulDriveByteCounter < ulDriveByteSize )
{
2022-05-15 15:17:49 +02:00
int iBytesToShred = 0 ; //Bytes that will be overwritten in this chunk-iteration
2022-08-22 15:27:29 +02:00
if ( uiShredIterationCounter ! = ( SHRED_ITERATIONS - 1 ) )
2022-05-15 15:17:49 +02:00
{
2022-08-22 15:27:29 +02:00
//NOT last shred iteration --> generate new random data
tfng_prng_genrandom ( caTfngData , TFNG_DATA_SIZE ) ;
2022-05-15 15:17:49 +02:00
}
2022-05-14 14:06:16 +02:00
if ( ( ulDriveByteSize - ulDriveByteCounter ) < CHUNK_SIZE )
{
iBytesToShred = ( ulDriveByteSize - ulDriveByteCounter ) ;
}
else
{
iBytesToShred = CHUNK_SIZE ;
}
2022-08-22 15:27:29 +02:00
int iByteShredded = write ( driveFileDiscr , caTfngData , iBytesToShred ) ;
2022-05-14 14:06:16 +02:00
if ( iByteShredded < = 0 )
{
2022-05-15 15:17:49 +02:00
std : : string errorMsg ( strerror ( iByteShredded ) ) ;
Logger : : logThis ( ) - > error ( " Shred-Task: Write to drive failed! " + errorMsg + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
perror ( " unable to write random data " ) ;
cleanup ( ) ;
return - 1 ;
}
ulDriveByteCounter + = iByteShredded ;
2022-05-14 15:21:14 +02:00
ulDriveByteOverallCount + = iByteShredded ;
d32Percent = this - > calcProgress ( ) ;
2022-08-22 18:35:27 +02:00
drive - > sShredSpeed . ulSpeedMetricBytesWritten + = iByteShredded ;
2022-05-14 14:06:16 +02:00
# ifdef LOG_LEVEL_HIGH
2022-05-14 15:21:14 +02:00
Logger : : logThis ( ) - > info ( " Shred-Task: ByteCount: " + to_string ( ulDriveByteCounter ) + " - iteration: " + to_string ( ( uiShredIterationCounter + 1 ) ) + " - progress: " + to_string ( d32Percent ) + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
# endif
2022-05-14 15:21:14 +02:00
if ( ( d32Percent - d32TmpPercent ) > = 0.01 )
2022-05-14 14:06:16 +02:00
{
2022-06-30 00:32:13 +02:00
//set shred percantage
2022-05-14 14:06:16 +02:00
drive - > setTaskPercentage ( d32TmpPercent ) ;
d32TmpPercent = d32Percent ;
2022-06-30 00:32:13 +02:00
//signal process in shreding
2022-05-14 14:06:16 +02:00
write ( * ipSignalFd , " A " , 1 ) ;
}
if ( drive - > state ! = Drive : : SHRED_ACTIVE )
{
drive - > setTaskPercentage ( 0 ) ;
d32Percent = 0.00 ;
d32TmpPercent = 0.00 ;
ulDriveByteCounter = 0U ;
Logger : : logThis ( ) - > info ( " Aborted shred for: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) ) ;
cleanup ( ) ;
return - 1 ;
}
2022-08-22 15:27:29 +02:00
//end one chunk write
}
2022-05-14 14:06:16 +02:00
if ( 0 ! = iRewindDrive ( driveFileDiscr ) )
{
2022-08-22 15:27:29 +02:00
Logger : : logThis ( ) - > error ( " Shred-Task: Unable to rewind drive! - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
cleanup ( ) ;
return - 1 ;
}
2022-08-22 15:27:29 +02:00
//end one shred iteration
}
//end of all shred iteratio
tfng_prng_seedkey ( NULL ) ; //reset random generator
2022-05-14 14:06:16 +02:00
2022-09-27 21:58:59 +02:00
drive - > bWasShredded = true ;
Logger : : logThis ( ) - > info ( " Shred-Task finished - Drive: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) + " @ " + address . str ( ) ) ;
# ifdef ZERO_CHECK
drive - > state = Drive : : CHECK_ACTIVE ;
Logger : : logThis ( ) - > info ( " Check-Task started - Drive: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) + " @ " + address . str ( ) ) ;
2022-11-24 20:41:23 +01:00
drive - > u32DriveChecksumAfterShredding = uiCalcChecksum ( driveFileDiscr , drive , ipSignalFd ) ;
2022-05-14 14:06:16 +02:00
# ifdef LOG_LEVEL_HIGH
if ( drive - > u32DriveChecksumAferShredding ! = 0 )
{
2022-11-24 20:41:23 +01:00
Logger : : logThis ( ) - > info ( " Shred-Task: Checksum not zero: " + to_string ( drive - > u32DriveChecksumAfterShredding ) + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
}
else
{
2022-11-24 20:41:23 +01:00
Logger : : logThis ( ) - > info ( " Shred-Task: Checksum zero: " + to_string ( drive - > u32DriveChecksumAfterShredding ) + " - Drive: " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
}
# endif
# endif
# endif
2022-05-15 15:17:49 +02:00
cleanup ( ) ;
2022-09-27 21:58:59 +02:00
if ( ( drive - > state = = Drive : : SHRED_ACTIVE ) | | ( drive - > state = = Drive : : CHECK_ACTIVE ) )
2022-05-14 14:06:16 +02:00
{
drive - > state = Drive : : NONE ;
drive - > setTaskPercentage ( 0.0 ) ;
2022-11-24 20:41:23 +01:00
Printer : : getPrinter ( ) - > print ( drive ) ;
2022-09-27 21:58:59 +02:00
Logger : : logThis ( ) - > info ( " Finished shred/check for: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) ) ;
2022-05-14 14:06:16 +02:00
}
return 0 ;
}
/**
* \ brief calc shredding progress in %
* \ param current byte index of the drive
* \ param current shred iteration
* \ return double percentage
*/
2022-05-14 15:21:14 +02:00
double Shred : : calcProgress ( )
2022-05-14 14:06:16 +02:00
{
unsigned int uiMaxShredIteration = SHRED_ITERATIONS ;
2022-09-27 21:58:59 +02:00
# ifdef ZERO_CHECK
2022-05-14 14:06:16 +02:00
uiMaxShredIteration + + ; //increment because we will check after SHRED_ITERATIONS the drive for non-zero bytes
# endif
2022-05-14 15:21:14 +02:00
return ( double ) ( ( ( double ) ulDriveByteOverallCount ) / ( ( double ) this - > ulDriveByteSize * uiMaxShredIteration ) ) * 100.0f ;
2022-05-14 14:06:16 +02:00
}
int Shred : : iRewindDrive ( fileDescriptor file )
{
if ( 0 ! = lseek ( file , 0L , SEEK_SET ) )
{
perror ( " unable to rewind drive " ) ;
return - 1 ;
}
else
{
return 0 ;
}
}
unsigned long Shred : : getDriveSizeInBytes ( fileDescriptor file )
{
unsigned long ulDriveSizeTmp = lseek ( file , 0L , SEEK_END ) ;
if ( 0 ! = iRewindDrive ( file ) )
{
ulDriveSizeTmp = 0U ;
}
# ifdef DEMO_DRIVE_SIZE
ulDriveSizeTmp = DEMO_DRIVE_SIZE ;
# endif
return ulDriveSizeTmp ;
}
2022-05-14 15:21:14 +02:00
unsigned int Shred : : uiCalcChecksum ( fileDescriptor file , Drive * drive , int * ipSignalFd )
2022-05-14 14:06:16 +02:00
{
unsigned int uiChecksum = 0 ;
unsigned long ulDriveByteCounter = 0U ;
while ( ulDriveByteCounter < ulDriveByteSize )
{
int iBytesToCheck = 0 ;
if ( ( ulDriveByteSize - ulDriveByteCounter ) < CHUNK_SIZE )
{
iBytesToCheck = ( ulDriveByteSize - ulDriveByteCounter ) ;
}
else
{
iBytesToCheck = CHUNK_SIZE ;
}
2022-08-22 15:27:29 +02:00
int iReadBytes = read ( file , caReadBuffer , iBytesToCheck ) ;
2022-05-14 14:06:16 +02:00
for ( int iReadBytesCounter = 0U ; iReadBytesCounter < iReadBytes ; iReadBytesCounter + + )
{
2022-08-22 15:27:29 +02:00
uiChecksum + = caReadBuffer [ iReadBytesCounter ] ;
2022-05-14 14:06:16 +02:00
}
ulDriveByteCounter + = iReadBytes ;
2022-05-15 15:17:49 +02:00
ulDriveByteOverallCount + = iReadBytes ;
2022-05-14 15:21:14 +02:00
d32Percent = this - > calcProgress ( ) ;
2022-08-23 23:20:50 +02:00
drive - > sShredSpeed . ulSpeedMetricBytesWritten + = iReadBytes ;
2022-09-27 21:58:59 +02:00
2022-05-14 15:21:14 +02:00
# ifdef LOG_LEVEL_HIGH
Logger : : logThis ( ) - > info ( " Shred-Task (Checksum): ByteCount: " + to_string ( ulDriveByteCounter ) + " - progress: " + to_string ( d32Percent ) + " - Drive: " + drive - > getSerial ( ) ) ;
# endif
2022-09-27 21:58:59 +02:00
if ( ( ( d32Percent - d32TmpPercent ) > = 0.01 ) | | ( d32Percent = = 100.0 ) )
2022-05-14 15:21:14 +02:00
{
drive - > setTaskPercentage ( d32TmpPercent ) ;
d32TmpPercent = d32Percent ;
2022-09-27 21:58:59 +02:00
# ifdef LOG_LEVEL_HIGH
Logger : : logThis ( ) - > info ( " send progress signal to main loop (check) " ) ;
# endif
2022-05-14 15:21:14 +02:00
write ( * ipSignalFd , " A " , 1 ) ;
}
2022-05-14 14:06:16 +02:00
}
2022-09-27 21:58:59 +02:00
drive - > bWasChecked = true ;
2022-05-14 14:06:16 +02:00
return uiChecksum ;
}
void Shred : : cleanup ( )
{
close ( driveFileDiscr ) ;
2022-08-22 15:27:29 +02:00
close ( randomSrcFileDiscr ) ;
2022-05-14 14:06:16 +02:00
}