4 #include <c++utilities/conversion/stringconversion.h> 5 #include <c++utilities/io/catchiofailure.h> 7 #ifdef PLATFORM_WINDOWS 10 # include <sys/stat.h> 32 namespace BackupHelper {
42 static string backupDir;
66 if(originalStream.is_open()) {
67 originalStream.close();
70 backupStream.exceptions(ios_base::goodbit);
73 backupStream.open(backupPath, ios_base::in | ios_base::binary);
74 if(backupStream.is_open()) {
77 throwIoFailure(
"Backup/temporary file has not been created.");
80 std::remove(originalPath.c_str());
81 if(std::rename(backupPath.c_str(), originalPath.c_str()) != 0) {
85 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
86 originalStream.exceptions(ios_base::failbit | ios_base::badbit);
87 backupStream.open(backupPath, ios_base::in | ios_base::binary);
88 originalStream.open(originalPath, ios_base::out | ios_base::binary);
89 originalStream << backupStream.rdbuf();
93 throwIoFailure((
"Unable to restore original file from backup file \"" + backupPath +
"\" after failure.").data());
120 void createBackupFile(
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream)
124 #ifndef PLATFORM_WINDOWS 125 struct stat backupStat;
127 for(
unsigned int i = 0; ; ++i) {
128 if(backupDir.empty()) {
130 backupPath = originalPath +
'.' + numberToString(i) +
".bak";
132 backupPath = originalPath +
".bak";
135 const string fileName = BasicFileInfo::fileName(originalPath, i);
137 const string ext = BasicFileInfo::extension(originalPath);
138 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
140 backupPath = BasicFileInfo::containingDirectory(originalPath);
142 backupPath += backupDir;
144 backupPath += fileName;
146 backupPath += numberToString(i);
150 backupPath = backupDir;
152 backupPath += fileName;
154 backupPath += numberToString(i);
158 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
160 backupPath = BasicFileInfo::containingDirectory(originalPath);
162 backupPath += backupDir;
164 backupPath += fileName;
167 backupPath = backupDir;
169 backupPath += fileName;
175 #ifdef PLATFORM_WINDOWS 176 if(GetFileAttributes(backupPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
178 if(stat(backupPath.c_str(), &backupStat)) {
185 std::remove(backupPath.c_str());
187 if(originalStream.is_open()) {
188 originalStream.close();
191 if(std::rename(originalPath.c_str(), backupPath.c_str()) != 0) {
194 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
195 originalStream.exceptions(ios_base::failbit | ios_base::badbit);
197 if(backupStream.is_open()) {
198 backupStream.close();
200 backupStream.open(backupPath, ios_base::out | ios_base::binary);
202 originalStream.open(originalPath, ios_base::in | ios_base::binary);
204 backupStream << originalStream.rdbuf();
209 throwIoFailure(
"Unable to rename original file before rewriting it.");
214 if(originalStream.is_open()) {
215 originalStream.close();
218 if(backupStream.is_open()) {
219 backupStream.close();
222 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
223 backupStream.open(backupPath, ios_base::in | ios_base::binary);
228 if(std::rename(backupPath.c_str(), originalPath.c_str()) != 0) {
229 throwIoFailure((
"Unable to restore original file from backup file \"" + backupPath +
"\" after failure.").data());
231 throwIoFailure(
"Unable to open backup file.");
265 if(!backupPath.empty()) {
267 fileInfo.
addNotification(NotificationType::Information,
"Rewriting the file to apply changed tag information has been aborted.", context);
270 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
272 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
275 fileInfo.
addNotification(NotificationType::Information,
"Applying new tag information has been aborted.", context);
280 if(!backupPath.empty()) {
282 fileInfo.
addNotification(NotificationType::Critical,
"Rewriting the file to apply changed tag information failed.", context);
285 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
287 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
290 fileInfo.
addNotification(NotificationType::Critical,
"Applying new tag information failed.", context);
295 const char *what = catchIoFailure();
296 if(!backupPath.empty()) {
298 fileInfo.
addNotification(NotificationType::Critical,
"An IO error occured when rewriting the file to apply changed tag information.", context);
301 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
303 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
306 fileInfo.
addNotification(NotificationType::Critical,
"An IO error occured when applying tag information.", context);
308 throwIoFailure(what);
Contains utility classes helping to read and write streams.