You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // FileBackup.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file implements the common functionality for the configuration
  7. // utilities.
  8. #include <cerrno>
  9. #include <cstring>
  10. #include <cstdio>
  11. #include <sstream>
  12. #include <stdexcept>
  13. #include <fstream>
  14. #include "FileBackup.hpp"
  15. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  17. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  18. const std::string FileBackup::BackupSuffix(".bak");
  19. const std::string FileBackup::FailedSuffix(".failed");
  20. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  22. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  23. void
  24. FileBackup::CopyFile(std::string From, std::string To) {
  25. std::ifstream Input;
  26. Input.open(From.c_str());
  27. if (!Input) {
  28. std::string Temp;
  29. Temp = "Error opening the file " + From;
  30. Temp += " to read from: ";
  31. Temp += strerror(errno);
  32. throw std::runtime_error(Temp);
  33. }
  34. std::ofstream Output;
  35. Output.open(To.c_str(), std::ios::trunc);
  36. if (!Output) {
  37. std::string Temp;
  38. Temp = "Error opening the file " + To;
  39. Temp += " to copy to: ";
  40. Temp += strerror(errno);
  41. throw std::runtime_error(Temp);
  42. }
  43. if (!Input.eof()) { // Copy if there are characters.
  44. // Copying an empty file causes
  45. Output << Input.rdbuf(); // failbit to be set.
  46. }
  47. if (Output.bad() || Output.fail()) {
  48. std::string Temp;
  49. Temp = "Error copying " + From;
  50. Temp += " to " + To;
  51. Temp += ": ";
  52. Temp += strerror(errno);
  53. throw std::runtime_error(Temp);
  54. }
  55. Input.close();
  56. if (!Input) {
  57. std::string Temp;
  58. Temp = "Error closing the file " + From;
  59. Temp += ": ";
  60. Temp += strerror(errno);
  61. throw std::runtime_error(Temp);
  62. }
  63. Output.close();
  64. if (!Output) {
  65. std::string Temp;
  66. Temp = "Error closing the file " + To;
  67. Temp += ": ";
  68. Temp += strerror(errno);
  69. throw std::runtime_error(Temp);
  70. }
  71. }
  72. std::string
  73. FileBackup::GetBackupFileName(std::string File) {
  74. return File + BackupSuffix;
  75. }
  76. std::string
  77. FileBackup::GetFailedFileName(std::string File) {
  78. return File + FailedSuffix;
  79. }
  80. bool
  81. FileBackup::FileExists(std::string File) {
  82. bool Exists;
  83. std::ifstream Input;
  84. errno = 0;
  85. Input.open(File.c_str());
  86. if (ENOENT == errno) {
  87. Exists = false;
  88. } else {
  89. Exists = true;
  90. }
  91. Input.close();
  92. return Exists;
  93. }
  94. void
  95. FileBackup::CreateBackupFile(std::string File) {
  96. std::string FailedFileName;
  97. FailedFileName = GetFailedFileName(File);
  98. if (FileExists(FailedFileName)) { // Removed .failed file?
  99. if (0 != remove(FailedFileName.c_str())) {
  100. std::string Temp;
  101. Temp = "Unable to remove file " + FailedFileName;
  102. Temp += " created from a previous run: ";
  103. Temp += strerror(errno);
  104. throw std::runtime_error(Temp);
  105. }
  106. }
  107. bool ThisFileExists = FileExists(File);
  108. if (ThisFileExists) { // Back up if the file exists.
  109. try {
  110. CopyFile(File, GetBackupFileName(File));
  111. } catch (std::exception &e) {
  112. std::string Temp;
  113. Temp = "Error making a backup of " + File;
  114. Temp += ": ";
  115. Temp += e.what();
  116. throw std::runtime_error(Temp);
  117. }
  118. }
  119. OriginalFileExists[File] = ThisFileExists;
  120. }
  121. void
  122. FileBackup::RemoveAllBackupFiles() {
  123. bool ErrorOccurred = false;
  124. std::ostringstream ErrorMessage;
  125. for (FilenameContainer::iterator iFile = OriginalFileExists.begin();
  126. iFile != OriginalFileExists.end();
  127. iFile++) {
  128. std::string BackupFileName;
  129. if (iFile->second) { // Original file existed?
  130. BackupFileName = GetBackupFileName(iFile->first);
  131. if (0 != remove(BackupFileName.c_str())) { // Delete the backup file.
  132. ErrorMessage << "Unable to remove backup file " << BackupFileName
  133. << ": " << strerror(errno) << "\n";
  134. ErrorOccurred = true;
  135. }
  136. }
  137. }
  138. if (ErrorOccurred) {
  139. throw std::runtime_error(ErrorMessage.str());
  140. }
  141. }
  142. void
  143. FileBackup::RestoreAllFilesFromBackup() {
  144. bool ErrorOccurred = false;
  145. std::ostringstream ErrorMessage;
  146. for (FilenameContainer::iterator iFile = OriginalFileExists.begin();
  147. iFile != OriginalFileExists.end();
  148. iFile++) {
  149. std::string BackupFileName;
  150. std::string FailedFileName;
  151. if (FileExists(iFile->first)) {
  152. try {
  153. FailedFileName = GetFailedFileName(iFile->first);
  154. CopyFile(iFile->first, FailedFileName);
  155. } catch (std::exception &e) {
  156. ErrorMessage << "Error copying " << iFile->first << " to "
  157. << FailedFileName << ": " << e.what() << " \n";
  158. ErrorOccurred = true;
  159. }
  160. if (0 != remove(iFile->first.c_str())) { // Remove the new file.
  161. ErrorMessage << "Unable to remove backup file " << BackupFileName
  162. << ": " << strerror(errno) << "\n";
  163. ErrorOccurred = true;
  164. }
  165. }
  166. if (iFile->second) { // Original file existed?
  167. try { // Yes.
  168. BackupFileName = GetBackupFileName(iFile->first);
  169. CopyFile(BackupFileName, iFile->first);
  170. } catch (std::exception &e) {
  171. ErrorMessage << "Error restoring " << iFile->first << " from backup "
  172. << BackupFileName << ": " << e.what() << " \n";
  173. ErrorOccurred = true;
  174. }
  175. }
  176. }
  177. if (ErrorOccurred) {
  178. throw std::runtime_error(ErrorMessage.str());
  179. }
  180. }