diff --git a/include/drive.h b/include/drive.h index 6c76568..6d08433 100644 --- a/include/drive.h +++ b/include/drive.h @@ -22,12 +22,13 @@ public: FROZEN } state; - struct { + struct + { time_t u32ShredTimeDelta; std::chrono::time_point chronoShredTimestamp; unsigned long ulWrittenBytes; } sShredSpeed; - + bool bWasShredded = false; bool bWasDeleteted = false; bool bIsOffline = false; diff --git a/makefile b/makefile index 9761a26..de76db9 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ #### PROJECT SETTINGS #### # The name of the executable to be created -BIN_NAME := reHDD +BIN_NAME := shredTest # Compiler used CXX ?= g++ # Extension of source files used in the project diff --git a/reHDDShred b/reHDDShred new file mode 120000 index 0000000..e480691 --- /dev/null +++ b/reHDDShred @@ -0,0 +1 @@ +bin/release/reHDDShred \ No newline at end of file diff --git a/src/reHDD.cpp b/src/reHDD.cpp index 3c05ddc..97b3240 100644 --- a/src/reHDD.cpp +++ b/src/reHDD.cpp @@ -11,13 +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 std::mutex mxScannDrives; - -list listNewDrives; //store found drives that are updated every 5sec - -static list listDrives; //stores all drive data from scann thread - -TUI *ui; +static Drive* pDummyDrive; static uint8_t u8SelectedEntry; @@ -40,15 +34,15 @@ reHDD::reHDD(void) */ void reHDD::app_logic(void) { - ui = new TUI(); - ui->initTUI(); + pDummyDrive = new Drive("/dev/sdc"); + pDummyDrive->state = Drive::NONE; + pDummyDrive->bIsOffline = false; pipe(fdNewDrivesInformPipe); pipe(fdShredInformPipe); - thread thDevices(ThreadScannDevices); //start thread that scanns for drives - thread thUserInput(ThreadUserInput); //start thread that reads user input - thread thCheckFrozenDrives(ThreadCheckFrozenDrives); //start thread that checks timeout for drives + getSelectedDrive()->state = Drive::TaskState::SHRED_ACTIVE; + thread(ThreadShred).detach(); while(1) { @@ -58,457 +52,40 @@ void reHDD::app_logic(void) select(FD_SETSIZE, &selectSet, NULL, NULL, NULL); - if(FD_ISSET(fdNewDrivesInformPipe[0], &selectSet)) - { - mxScannDrives.lock(); - char dummy; - read (fdNewDrivesInformPipe[0],&dummy,1); - filterNewDrives(&listDrives, &listNewDrives); //filter and copy to app logic vector - printDrives(&listDrives); - mxScannDrives.unlock(); - } if(FD_ISSET(fdShredInformPipe[0], &selectSet)) { char dummy; read (fdShredInformPipe[0],&dummy,1); -#ifdef LOG_LEVEL_HIGH - Logger::logThis()->info("got progress signal from a shred task"); -#endif + + stringstream stream; + stream << fixed << setprecision(3) << (getSelectedDrive()->getTaskPercentage()); + string sState = "Shredding: " + stream.str() + "%"; + + std::ostringstream out; + double dDeltaSec = ((double)((getSelectedDrive()->sShredSpeed.u32ShredTimeDelta)/1000000000.0)); //convert nano in sec + double speed = ((getSelectedDrive()->sShredSpeed.ulWrittenBytes/1000000.0)/dDeltaSec); + char s[25]; + sprintf(s, "%0.2lf MB/s", speed); + out << s; + Logger::logThis()->info(sState + " - " + out.str()); } - ui->updateTUI(&listDrives, u8SelectedEntry); } //endless loop - thDevices.join(); - thUserInput.join(); - thCheckFrozenDrives.join(); } Drive* reHDD::getSelectedDrive() { - if(u8SelectedEntry < listDrives.size() ) - { - list::iterator it = listDrives.begin(); - advance(it, u8SelectedEntry); - return &(*it); - } - else - { - Logger::logThis()->warning("selected drive not present"); - return {}; - } -} - -void reHDD::ThreadScannDevices() -{ - while(true) - { - mxScannDrives.lock(); - listNewDrives.clear(); - searchDrives(&listNewDrives); //search for new drives and store them in list - filterIgnoredDrives(&listNewDrives); //filter out ignored drives - addSMARTData(&listNewDrives); //add S.M.A.R.T. Data to the drives - mxScannDrives.unlock(); - write(fdNewDrivesInformPipe[1], "A",1); - sleep(5); //sleep 5 sec - } -} - -void reHDD::ThreadCheckFrozenDrives() -{ - while(true) - { - mxScannDrives.lock(); - for(auto it = begin(listDrives); it != end(listDrives); ++it) - { - if(it->state == Drive::SHRED_ACTIVE) - { - it->checkFrozenDrive(); - } - } - mxScannDrives.unlock(); - sleep(13); //sleep 13 sec - } -} - -void reHDD::ThreadUserInput() -{ - while(true) - { - // cout << TUI::readUserInput() << endl; - switch (TUI::readUserInput()) - { - case TUI::UserInput::DownKey: - //cout << "Down" << endl; - handleArrowKey(TUI::UserInput::DownKey); - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::UpKey: - //cout << "Up" << endl; - handleArrowKey(TUI::UserInput::UpKey); - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::Undefined: - //cout << "Undefined" << endl; - break; - case TUI::UserInput::Abort: - //cout << "Abort" << endl; - handleAbort(); - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::Delete: - //cout << "Delete" << endl; - - if (getSelectedDrive() != nullptr) - { - if(getSelectedDrive()->state == Drive::NONE) - { - getSelectedDrive()->state = Drive::DELETE_SELECTED; - } - } - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::Shred: - //cout << "Shred" << endl; - - if (getSelectedDrive() != nullptr) - { - if(getSelectedDrive()->state == Drive::NONE) - { - getSelectedDrive()->state = Drive::SHRED_SELECTED; - } - } - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::Enter: - //cout << "Enter" << endl; - handleEnter(); - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - case TUI::UserInput::ESC: - //cout << "ESC" << endl; - handleESC(); - ui->updateTUI(&listDrives, u8SelectedEntry); - break; - default: - break; - } - } + return pDummyDrive; } void reHDD::ThreadShred() { if (getSelectedDrive() != nullptr) { + Logger::logThis()->info("Starting Shred Thread"); getSelectedDrive()->setActionStartTimestamp(); //save timestamp at start of shredding Shred* pShredTask = new Shred(); //create new shred task pShredTask->shredDrive(getSelectedDrive(), &fdShredInformPipe[1]); //start new shred task delete pShredTask; //delete shred task - ui->updateTUI(&listDrives, u8SelectedEntry); } } -void reHDD::ThreadDelete() -{ - if (getSelectedDrive() != nullptr) - { - getSelectedDrive()->setActionStartTimestamp(); //save timestamp at start of deleting - Delete::deleteDrive(getSelectedDrive()); //blocking, no thread - getSelectedDrive()->state = Drive::TaskState::NONE; //delete finished - getSelectedDrive()->bWasDeleteted = true; - Logger::logThis()->info("Finished delete for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial()); - ui->updateTUI(&listDrives, u8SelectedEntry); - } -} - -void reHDD::filterNewDrives(list * plistOldDrives, list * plistNewDrives) -{ - list ::iterator itOld; //Iterator for current (old) drive list - list ::iterator itNew; //Iterator for new drive list that was created from to scann thread - - //remove offline old drives from previously run - for (itOld = plistOldDrives->begin(); itOld != plistOldDrives->end();) - { - if(itOld->bIsOffline == true) - { - Logger::logThis()->warning("Offline drive found: " + itOld->getPath()); - itOld = plistOldDrives->erase(itOld); - /* - if(plistOldDrives->size() > 0){ //This can be a risk if the user starts a task for the selected drive and the selected drive changes - u8SelectedEntry = 0U; - } - */ - } - else - { - ++itOld; - } - } - - //search offline drives and mark them - for (itOld = plistOldDrives->begin(); itOld != plistOldDrives->end(); ++itOld) - { - itOld->bIsOffline = true; //set offline befor seachring in the new list - for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end();) - { - if((itOld->getSerial() == itNew->getSerial()) || (itOld->getPath() == itNew->getPath())) - { - itOld->bIsOffline = false; //drive is still attached -#ifdef LOG_LEVEL_HIGH - Logger::logThis()->info("Delete new drive, because allready attached: " + itNew->getModelName()); -#endif - itNew = plistNewDrives->erase(itNew); //This drive is allready attached, remove from new list - } - else - { - ++itNew; - } - } - } - - //mark offline old drives - for (itOld = plistOldDrives->begin(); itOld != plistOldDrives->end(); ++itOld) - { - if(itOld->bIsOffline == true) - { - //cout << "offline drive found: " << itOld->getPath() << endl; - Logger::logThis()->warning("Mark offline drive found: " + itOld->getPath()); - itOld->state = Drive::NONE; //clear state --> shred task will terminate - } - } - - //add new drives to drive list - for (itNew = plistNewDrives->begin(); itNew != plistNewDrives->end(); ++itNew) - { - plistOldDrives->push_back(*itNew); - Logger::logThis()->info("Add new drive: " + itNew->getModelName()); - } - plistNewDrives->clear(); -} - -/** - * \brief search attached drives on /dev/sd* - * \param pointer of list * plistDrives - * \return void - */ -void reHDD::searchDrives(list * plistDrives) -{ - Logger::logThis()->info("--> search drives <--"); - char * cLine = NULL; - size_t len = 0; - - FILE* outputfileHwinfo = popen("lsblk -I 8 -d -o NAME", "r"); - - if (outputfileHwinfo == NULL) - { - Logger::logThis()->error("Unable to scan attached drives"); - exit(EXIT_FAILURE); - } - - while ((getline(&cLine, &len, outputfileHwinfo)) != -1) - { - if (string(cLine).length() == 4) - { - Drive* tmpDrive = new Drive("/dev/" + string(cLine).substr(0, 3)); - tmpDrive->state = Drive::NONE; - tmpDrive->bIsOffline = false; - plistDrives->push_back(*tmpDrive); - //Logger::logThis()->info("drive found: " + tmpDrive->getPath()); - } - } - pclose(outputfileHwinfo); -} - -/** - * \brief filter out drives that are listed in "ignoreDrives.conf" - * \param pointer of list * plistDrives - * \return void - */ -void reHDD::filterIgnoredDrives(list * plistDrives) -{ - list> vtlIgnoredDevices; //store drives from ingnore file - ifstream input( "ignoreDrives.conf" ); //read ingnore file - - for(string sLine; getline( input, sLine );) - { - Logger::logThis()->info("read uuid: " + sLine); - vtlIgnoredDevices.emplace_back(sLine); //add found path and uuid from ignore file to vector - } - //loop through found entries in ingnore file - for(auto row : vtlIgnoredDevices) - { - list ::iterator it; - for (it = plistDrives->begin(); it != plistDrives->end(); ++it) - { - string sUUID; - char * cLine = NULL; - size_t len = 0; - string sCMD = "blkid "; - sCMD.append(it->getPath()); - //cout << "cmd: " << sCMD << endl; - FILE* outputfileBlkid = popen(sCMD.c_str(), "r"); //get UUID from drive - if (outputfileBlkid == NULL) - { - exit(EXIT_FAILURE); - } - - while ((getline(&cLine, &len, outputfileBlkid)) != -1) //parse UUID from blkid - { - if (string(cLine).find("PTUUID") != string::npos) - { - string sBlkidOut = string(cLine); - sBlkidOut.erase(0, 18); - sBlkidOut.erase(8, sBlkidOut.length()); - sUUID = sBlkidOut; - //cout << "blkid uuid:" << sUUID << endl; - } - } - pclose(outputfileBlkid); - //cout << "blkid uuid:" << sUUID << endl; - - if (!get<0>(row).compare(sUUID)) //compare uuid from ignore file and uuid from drive - { - // same uuid found than in ignore file --> ignore this drive -#ifdef LOG_LEVEL_HIGH - Logger::logThis()->info("same uuid found than in ignore file --> ignore this drive: " + it->getPath()); -#endif - it = plistDrives->erase(it); - it--; - } - } - } -} - -/** - * \brief print drives with all information - * \param pointer of list * plistDrives - * \return void - */ -void reHDD::printDrives(list * plistDrives) -{ -#ifdef LOG_LEVEL_HIGH - Logger::logThis()->info("------------DRIVES START------------"); - //cout << "------------DRIVES---------------" << endl; - list ::iterator it; - uint8_t u8Index = 0; - for (it = plistDrives->begin(); it != plistDrives->end(); ++it) - { - /* - cout << " Drive: " << distance(pvecDrives->begin(), it) << endl; - cout << "Path: " << it->getPath() << endl; - cout << "ModelFamily: " << it->getModelFamily() << endl; - cout << "ModelName: " << it->getModelName() << endl; - cout << "Capacity: " << it->getCapacity() << endl; - cout << "Serial: " << it->getSerial() << endl; - cout << "PowerOnHours: " << it->getPowerOnHours() << endl; - cout << "PowerCycle: " << it->getPowerCycles() << endl; - cout << "ErrorCount: " << it->getErrorCount() << endl; - cout << endl;*/ - - ostringstream address; - address << (void const *)&(*it); - Logger::logThis()->info(to_string(u8Index++) + ": " + it->getPath() + " - " + it->getModelFamily() + " - " + it->getSerial() + " @" + address.str()); - } - Logger::logThis()->info("------------DRIVES END--------------"); - //cout << "---------------------------------" << endl; -#endif -} - -/** - * \brief add S.M.A.R.T data from SMART - * \param pointer of list * plistDrives - * \return void - */ -void reHDD::addSMARTData(list * plistDrives) -{ - list ::iterator it; - for (it = plistDrives->begin(); it != plistDrives->end(); ++it) - { - Drive* pTmpDrive = iterator_to_pointer::iterator > (it); - SMART::readSMARTData(pTmpDrive); - } -} - -void reHDD::handleArrowKey(TUI::UserInput userInput) -{ - int8_t u8EntrySize = (int8_t) listDrives.size(); - switch (userInput) - { - case TUI::UserInput::DownKey: - u8SelectedEntry++; - if(u8SelectedEntry >= u8EntrySize) - { - u8SelectedEntry = 0; - } - break; - case TUI::UserInput::UpKey: - if(u8SelectedEntry == 0) - { - u8SelectedEntry = (u8EntrySize-1); - } - else - { - u8SelectedEntry--; - } - break; - default: - u8SelectedEntry = 0; - break; - } - - Logger::logThis()->info("ArrowKey - selected drive: " + to_string(u8SelectedEntry)); -} - -void reHDD::handleEnter() -{ - if (getSelectedDrive() != nullptr) - { - if(getSelectedDrive()->state == Drive::TaskState::SHRED_SELECTED) - { - Logger::logThis()->info("Started shred for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial()); - getSelectedDrive()->state = Drive::TaskState::SHRED_ACTIVE; - //task for drive is running --> don´t show more task options - thread(ThreadShred).detach(); - } - - if(getSelectedDrive()->state == Drive::TaskState::DELETE_SELECTED) - { - Logger::logThis()->info("Started delete for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial()); - getSelectedDrive()->state = Drive::TaskState::DELETE_ACTIVE; - //task for drive is running --> don´t show more task options - thread(ThreadDelete).detach(); - } - } -} - -void reHDD::handleESC() -{ - if (getSelectedDrive() != nullptr) - { - if(getSelectedDrive()->state == Drive::TaskState::SHRED_SELECTED) - { - getSelectedDrive()->state = Drive::TaskState::NONE; - //task for drive is selected --> remove selection - } - - if(getSelectedDrive()->state == Drive::TaskState::DELETE_SELECTED) - { - getSelectedDrive()->state = Drive::TaskState::NONE; - //task for drive is selected --> remove selection - } - } -} - -void reHDD::handleAbort() -{ - if (getSelectedDrive() != nullptr) - { - if(getSelectedDrive()->state == Drive::SHRED_ACTIVE || getSelectedDrive()->state == Drive::DELETE_ACTIVE ) - { - getSelectedDrive()->state = Drive::NONE; - Logger::logThis()->info("Abort-Shred-Signal for: " + getSelectedDrive()->getModelName() + "-" + getSelectedDrive()->getSerial()); - //task for drive is running --> remove selection - } - } -} - - - diff --git a/src/shred.cpp b/src/shred.cpp index 8476e2d..f28af85 100644 --- a/src/shred.cpp +++ b/src/shred.cpp @@ -75,7 +75,7 @@ int Shred::shredDrive(Drive* drive, int* ipSignalFd) { 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)) { diff --git a/src/tui.cpp b/src/tui.cpp index 2a02ee6..4fcd128 100644 --- a/src/tui.cpp +++ b/src/tui.cpp @@ -508,7 +508,8 @@ string TUI::formatTimeDuration(time_t u32Duration) return out.str(); } -string TUI::formatSpeed(time_t u32ShredTimeDelta, unsigned long ulWrittenBytes){ +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);