301 lines
10 KiB
C++
301 lines
10 KiB
C++
/**
|
|
* @file shred.cpp
|
|
* @brief shred drive
|
|
* @author hendrik schutter
|
|
* @date 22.08.2022
|
|
*/
|
|
|
|
#include "../include/reHDD.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include "../tfnoisegen/tfprng.h"
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
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)
|
|
{
|
|
ostringstream address;
|
|
address << (void const *)&(*drive);
|
|
Logger::logThis()->info("Shred-Task started - Drive: " + drive->getModelName() + "-" + drive->getSerial() + " @" + address.str());
|
|
|
|
#ifdef DRYRUN
|
|
for(int i = 0; i<=500; i++)
|
|
{
|
|
if(drive->state != Drive::SHRED_ACTIVE)
|
|
{
|
|
return 0;
|
|
}
|
|
drive->setTaskPercentage(i+0.05);
|
|
write(*ipSignalFd, "A",1);
|
|
usleep(20000);
|
|
}
|
|
#endif
|
|
|
|
#ifndef DRYRUN
|
|
const char *cpDrivePath = drive->getPath().c_str();
|
|
unsigned char ucKey[TFNG_KEY_SIZE];
|
|
|
|
//open random source
|
|
randomSrcFileDiscr = open(randomsrc, O_RDONLY | O_LARGEFILE);
|
|
if (randomSrcFileDiscr == -1)
|
|
{
|
|
std::string errorMsg(strerror(randomSrcFileDiscr));
|
|
Logger::logThis()->error("Shred-Task: Open random source failed! " + errorMsg + " - Drive: " + drive->getSerial());
|
|
perror(randomsrc);
|
|
cleanup();
|
|
return -1;
|
|
}
|
|
|
|
//open disk
|
|
driveFileDiscr = open(cpDrivePath, O_RDWR | O_LARGEFILE);
|
|
if (driveFileDiscr == -1)
|
|
{
|
|
std::string errorMsg(strerror(driveFileDiscr));
|
|
Logger::logThis()->error("Shred-Task: Open drive failed! " + errorMsg + " - Drive: " + drive->getSerial());
|
|
perror(cpDrivePath);
|
|
cleanup();
|
|
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);
|
|
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
|
|
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++)
|
|
{
|
|
unsigned long ulDriveByteCounter = 0U; //used for one shred-iteration to keep track of the current drive position
|
|
|
|
if(uiShredIterationCounter == (SHRED_ITERATIONS-1))
|
|
{
|
|
//last shred iteration --> overwrite (just the write chunk) bytes with zeros instead with random data
|
|
memset(caTfngData, 0U, CHUNK_SIZE);
|
|
}
|
|
|
|
while (ulDriveByteCounter < ulDriveByteSize)
|
|
{
|
|
int iBytesToShred = 0; //Bytes that will be overwritten in this chunk-iteration
|
|
|
|
if(uiShredIterationCounter != (SHRED_ITERATIONS-1))
|
|
{
|
|
//NOT last shred iteration --> generate new random data
|
|
tfng_prng_genrandom(caTfngData, TFNG_DATA_SIZE);
|
|
}
|
|
|
|
if((ulDriveByteSize-ulDriveByteCounter) < CHUNK_SIZE)
|
|
{
|
|
iBytesToShred = (ulDriveByteSize-ulDriveByteCounter);
|
|
}
|
|
else
|
|
{
|
|
iBytesToShred = CHUNK_SIZE;
|
|
}
|
|
|
|
int iByteShredded = write(driveFileDiscr, caTfngData, iBytesToShred);
|
|
|
|
if(iByteShredded <= 0)
|
|
{
|
|
std::string errorMsg(strerror(iByteShredded));
|
|
Logger::logThis()->error("Shred-Task: Write to drive failed! " + errorMsg + " - Drive: " + drive->getSerial());
|
|
perror("unable to write random data");
|
|
cleanup();
|
|
return -1;
|
|
}
|
|
|
|
ulDriveByteCounter += iByteShredded;
|
|
ulDriveByteOverallCount += iByteShredded;
|
|
d32Percent = this->calcProgress();
|
|
drive->sShredSpeed.ulSpeedMetricBytesWritten += iByteShredded;
|
|
|
|
#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());
|
|
#endif
|
|
if((d32Percent-d32TmpPercent) >= 0.01)
|
|
{
|
|
//set shred percantage
|
|
drive->setTaskPercentage(d32TmpPercent);
|
|
d32TmpPercent = d32Percent;
|
|
//signal process in shreding
|
|
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;
|
|
}
|
|
//end one chunk write
|
|
}
|
|
if(0 != iRewindDrive(driveFileDiscr))
|
|
{
|
|
Logger::logThis()->error("Shred-Task: Unable to rewind drive! - Drive: " + drive->getSerial());
|
|
cleanup();
|
|
return -1;
|
|
}
|
|
//end one shred iteration
|
|
}
|
|
//end of all shred iteratio
|
|
|
|
tfng_prng_seedkey(NULL); //reset random generator
|
|
|
|
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());
|
|
drive->u32DriveChecksumAfterShredding = uiCalcChecksum(driveFileDiscr, drive, ipSignalFd);
|
|
#ifdef LOG_LEVEL_HIGH
|
|
if (drive->u32DriveChecksumAferShredding != 0)
|
|
{
|
|
Logger::logThis()->info("Shred-Task: Checksum not zero: " + to_string(drive->u32DriveChecksumAfterShredding) + " - Drive: " + drive->getSerial());
|
|
}
|
|
else
|
|
{
|
|
Logger::logThis()->info("Shred-Task: Checksum zero: " + to_string(drive->u32DriveChecksumAfterShredding) + " - Drive: " + drive->getSerial());
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
cleanup();
|
|
|
|
if((drive->state == Drive::SHRED_ACTIVE) || (drive->state == Drive::CHECK_ACTIVE))
|
|
{
|
|
drive->state= Drive::NONE;
|
|
drive->setTaskPercentage(0.0);
|
|
Printer::getPrinter()->print(drive);
|
|
Logger::logThis()->info("Finished shred/check for: " + drive->getModelName() + "-" + drive->getSerial());
|
|
}
|
|
return 0;
|
|
}
|
|
/**
|
|
* \brief calc shredding progress in %
|
|
* \param current byte index of the drive
|
|
* \param current shred iteration
|
|
* \return double percentage
|
|
*/
|
|
double Shred::calcProgress()
|
|
{
|
|
unsigned int uiMaxShredIteration = SHRED_ITERATIONS;
|
|
|
|
#ifdef ZERO_CHECK
|
|
uiMaxShredIteration++; //increment because we will check after SHRED_ITERATIONS the drive for non-zero bytes
|
|
#endif
|
|
return (double) (((double) ulDriveByteOverallCount) / ((double)this->ulDriveByteSize*uiMaxShredIteration))*100.0f;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
unsigned int Shred::uiCalcChecksum(fileDescriptor file,Drive* drive, int* ipSignalFd)
|
|
{
|
|
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;
|
|
}
|
|
int iReadBytes = read(file, caReadBuffer, iBytesToCheck);
|
|
for (int iReadBytesCounter = 0U; iReadBytesCounter < iReadBytes; iReadBytesCounter++)
|
|
{
|
|
uiChecksum += caReadBuffer[iReadBytesCounter];
|
|
}
|
|
ulDriveByteCounter += iReadBytes;
|
|
ulDriveByteOverallCount += iReadBytes;
|
|
d32Percent = this->calcProgress();
|
|
drive->sShredSpeed.ulSpeedMetricBytesWritten += iReadBytes;
|
|
|
|
#ifdef LOG_LEVEL_HIGH
|
|
Logger::logThis()->info("Shred-Task (Checksum): ByteCount: " + to_string(ulDriveByteCounter) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial());
|
|
#endif
|
|
|
|
if(((d32Percent-d32TmpPercent) >= 0.01) || (d32Percent == 100.0))
|
|
{
|
|
drive->setTaskPercentage(d32TmpPercent);
|
|
d32TmpPercent = d32Percent;
|
|
#ifdef LOG_LEVEL_HIGH
|
|
Logger::logThis()->info("send progress signal to main loop (check)");
|
|
#endif
|
|
write(*ipSignalFd, "A",1);
|
|
}
|
|
}
|
|
drive->bWasChecked = true;
|
|
return uiChecksum;
|
|
}
|
|
|
|
void Shred::cleanup()
|
|
{
|
|
close(driveFileDiscr);
|
|
close(randomSrcFileDiscr);
|
|
} |