forked from localhorst/reHDD
using now own shred impl with check if the complete drive is full of zeros after shredding
This commit is contained in:
258
src/shred.cpp
Normal file
258
src/shred.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
/**
|
||||
* @file shred.cpp
|
||||
* @brief shred drive
|
||||
* @author hendrik schutter
|
||||
* @date 03.05.2020
|
||||
*/
|
||||
|
||||
#include "../include/reHDD.h"
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
#ifdef DRYRUN
|
||||
for(int i = 0; i<=500; i++)
|
||||
{
|
||||
if(drive->state != Drive::SHRED_ACTIVE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
drive->setTaskPercentage(i+0.05);
|
||||
write(*ipSignalFd, "A",1);
|
||||
usleep(20000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DRYRUN
|
||||
const char *cpDrivePath = drive->getPath().c_str();
|
||||
|
||||
//open random source
|
||||
randomSrcFileDiscr = open(randomsrc, O_RDONLY | O_LARGEFILE);
|
||||
if (randomSrcFileDiscr == -1)
|
||||
{
|
||||
perror(randomsrc);
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//open disk
|
||||
driveFileDiscr = open(cpDrivePath, O_RDWR | O_LARGEFILE);
|
||||
if (driveFileDiscr == -1)
|
||||
{
|
||||
perror(cpDrivePath);
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->ulDriveByteSize = getDriveSizeInBytes(driveFileDiscr);
|
||||
|
||||
#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;
|
||||
|
||||
if(uiShredIterationCounter == (SHRED_ITERATIONS-1))
|
||||
{
|
||||
//last shred iteration --> overwrite with zeros instead with random data
|
||||
memset(caChunk, 0U, CHUNK_SIZE);
|
||||
}
|
||||
|
||||
while (ulDriveByteCounter < ulDriveByteSize)
|
||||
{
|
||||
int iBytesToShred = 0;
|
||||
|
||||
if((ulDriveByteSize-ulDriveByteCounter) < CHUNK_SIZE)
|
||||
{
|
||||
iBytesToShred = (ulDriveByteSize-ulDriveByteCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iBytesToShred = CHUNK_SIZE;
|
||||
}
|
||||
|
||||
if(uiShredIterationCounter != (SHRED_ITERATIONS-1))
|
||||
{
|
||||
//NOT last shred iteration --> overwrite with random data
|
||||
int iReadBytes = read(randomSrcFileDiscr, caChunk, iBytesToShred);
|
||||
if (iReadBytes > 0)
|
||||
{
|
||||
iBytesToShred = iReadBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("unable to read random data");
|
||||
cleanup();
|
||||
return -1;;
|
||||
}
|
||||
}
|
||||
|
||||
int iByteShredded = write(driveFileDiscr, caChunk, iBytesToShred);
|
||||
|
||||
if(iByteShredded <= 0)
|
||||
{
|
||||
perror("unable to write random data");
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(fsync(driveFileDiscr) != 0)
|
||||
{
|
||||
perror("unable to flush random data");
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
ulDriveByteCounter += iByteShredded;
|
||||
|
||||
d32Percent = this->calcProgress(ulDriveByteCounter, (uiShredIterationCounter+1));
|
||||
|
||||
#ifdef LOG_LEVEL_HIGH
|
||||
Logger::logThis()->info("Shred-Task: ByteCount: " + to_string(ulDriveByteCounter) + " - progress: " + to_string(d32Percent) + " - Drive: " + drive->getSerial());
|
||||
#endif
|
||||
|
||||
if((d32Percent-d32TmpPercent) >= 0.09)
|
||||
{
|
||||
drive->setTaskPercentage(d32TmpPercent);
|
||||
d32TmpPercent = d32Percent;
|
||||
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 shred iteration
|
||||
|
||||
if(0 != iRewindDrive(driveFileDiscr))
|
||||
{
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
} //end all shred iterations
|
||||
|
||||
#ifdef ZERO_CHECK_ALERT
|
||||
drive->u32DriveChecksumAferShredding = uiCalcChecksum(driveFileDiscr);
|
||||
#ifdef LOG_LEVEL_HIGH
|
||||
if (drive->u32DriveChecksumAferShredding != 0)
|
||||
{
|
||||
Logger::logThis()->info("Shred-Task: Checksum not zero: " + to_string(drive->u32DriveChecksumAferShredding) + " - Drive: " + drive->getSerial());
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::logThis()->info("Shred-Task: Checksum zero: " + to_string(drive->u32DriveChecksumAferShredding) + " - Drive: " + drive->getSerial());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(drive->state == Drive::SHRED_ACTIVE)
|
||||
{
|
||||
drive->bWasShredded = true;
|
||||
drive->state= Drive::NONE;
|
||||
drive->setTaskPercentage(0.0);
|
||||
Logger::logThis()->info("Finished shred 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 long ulDriveByteIndex, unsigned int uiIteration)
|
||||
{
|
||||
unsigned int uiMaxShredIteration = SHRED_ITERATIONS;
|
||||
|
||||
#ifdef ZERO_CHECK_ALERT
|
||||
uiMaxShredIteration++; //increment because we will check after SHRED_ITERATIONS the drive for non-zero bytes
|
||||
#endif
|
||||
|
||||
return (double) (100.0f/((double)this->ulDriveByteSize)*((double) ulDriveByteIndex) / ((double) uiIteration / (double) uiMaxShredIteration) );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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, caChunk, iBytesToCheck);
|
||||
|
||||
for (int iReadBytesCounter = 0U; iReadBytesCounter < iReadBytes; iReadBytesCounter++)
|
||||
{
|
||||
uiChecksum += caChunk[iReadBytesCounter];
|
||||
}
|
||||
ulDriveByteCounter += iReadBytes;
|
||||
}
|
||||
return uiChecksum;
|
||||
}
|
||||
|
||||
void Shred::cleanup()
|
||||
{
|
||||
close(driveFileDiscr);
|
||||
close( randomSrcFileDiscr);
|
||||
}
|
Reference in New Issue
Block a user