// FileBackup.cpp // // Copyright (C) 2011, ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // This file implements the common functionality for the configuration // utilities. #include #include #include #include #include #include #include #include "FileBackup.hpp" ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Configuration. //////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// const std::string FileBackup::BackupSuffix(".bak"); const std::string FileBackup::FailedSuffix(".failed"); ////////////////////////////////////////////////////////////////////////////////////////////////////////// // End of configuration. ///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// void FileBackup::CopyFile(std::string From, std::string To) { std::ifstream Input; Input.open(From.c_str()); if (!Input) { std::string Temp; Temp = "Error opening the file " + From; Temp += " to read from: "; Temp += strerror(errno); throw std::runtime_error(Temp); } std::ofstream Output; Output.open(To.c_str(), std::ios::trunc); if (!Output) { std::string Temp; Temp = "Error opening the file " + To; Temp += " to copy to: "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output << Input.rdbuf(); if (Output.bad()) { // Copying an empty file causes // failbit to be set. std::string Temp; Temp = "Error copying " + From; Temp += " to " + To; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Input.close(); if (!Input) { std::string Temp; Temp = "Error closing the file " + From; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output.close(); if (Output.bad()) { std::string Temp; Temp = "Error closing the file " + To; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } } std::string FileBackup::GetBackupFileName(std::string File) { return File + BackupSuffix; } std::string FileBackup::GetFailedFileName(std::string File) { return File + FailedSuffix; } bool FileBackup::FileExists(std::string File) { bool Exists; std::ifstream Input; errno = 0; Input.open(File.c_str()); if (ENOENT == errno) { Exists = false; } else { Exists = true; } Input.close(); return Exists; } void FileBackup::CreateBackupFile(std::string File) { std::string FailedFileName; FailedFileName = GetFailedFileName(File); if (FileExists(FailedFileName)) { // Removed .failed file? if (0 != remove(FailedFileName.c_str())) { std::string Temp; Temp = "Unable to remove file " + FailedFileName; Temp += " created from a previous run: "; Temp += strerror(errno); throw std::runtime_error(Temp); } } bool ThisFileExists = FileExists(File); if (ThisFileExists) { // Back up if the file exists. try { CopyFile(File, GetBackupFileName(File)); } catch (std::exception &e) { std::string Temp; Temp = "Error making a backup of " + File; Temp += ": "; Temp += e.what(); throw std::runtime_error(Temp); } } OriginalFileExists[File] = ThisFileExists; } void FileBackup::RemoveAllBackupFiles() { bool ErrorOccurred = false; std::ostringstream ErrorMessage; for (FilenameContainer::iterator iFile = OriginalFileExists.begin(); iFile != OriginalFileExists.end(); iFile++) { std::string BackupFileName; if (iFile->second) { // Original file existed? BackupFileName = GetBackupFileName(iFile->first); if (0 != remove(BackupFileName.c_str())) { // Delete the backup file. ErrorMessage << "Unable to remove backup file " << BackupFileName << ": " << strerror(errno) << "\n"; ErrorOccurred = true; } } } if (ErrorOccurred) { throw std::runtime_error(ErrorMessage.str()); } } void FileBackup::RestoreAllFilesFromBackup() { bool ErrorOccurred = false; std::ostringstream ErrorMessage; for (FilenameContainer::iterator iFile = OriginalFileExists.begin(); iFile != OriginalFileExists.end(); iFile++) { std::string BackupFileName; std::string FailedFileName; if (FileExists(iFile->first)) { try { FailedFileName = GetFailedFileName(iFile->first); CopyFile(iFile->first, FailedFileName); } catch (std::exception &e) { ErrorMessage << "Error copying " << iFile->first << " to " << FailedFileName << ": " << e.what() << " \n"; ErrorOccurred = true; } if (0 != remove(iFile->first.c_str())) { // Remove the new file. ErrorMessage << "Unable to remove backup file " << BackupFileName << ": " << strerror(errno) << "\n"; ErrorOccurred = true; } } if (iFile->second) { // Original file existed? try { // Yes. BackupFileName = GetBackupFileName(iFile->first); CopyFile(BackupFileName, iFile->first); } catch (std::exception &e) { ErrorMessage << "Error restoring " << iFile->first << " from backup " << BackupFileName << ": " << e.what() << " \n"; ErrorOccurred = true; } } } if (ErrorOccurred) { throw std::runtime_error(ErrorMessage.str()); } }