4 #include <c++utilities/conversion/stringconversion.h> 5 #include <c++utilities/conversion/stringbuilder.h> 6 #include <c++utilities/io/catchiofailure.h> 8 #ifdef PLATFORM_WINDOWS 11 # include <sys/stat.h> 33 namespace BackupHelper {
43 static string backupDir;
68 if(originalStream.is_open()) {
69 originalStream.close();
72 backupStream.exceptions(ios_base::goodbit);
75 backupStream.open(backupPath, ios_base::in | ios_base::binary);
76 if(backupStream.is_open()) {
79 throwIoFailure(
"Backup/temporary file has not been created.");
82 std::remove(originalPath.c_str());
83 if(std::rename(backupPath.c_str(), originalPath.c_str()) != 0) {
87 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
88 originalStream.exceptions(ios_base::failbit | ios_base::badbit);
89 backupStream.open(backupPath, ios_base::in | ios_base::binary);
90 originalStream.open(originalPath, ios_base::out | ios_base::binary);
91 originalStream << backupStream.rdbuf();
95 throwIoFailure((
"Unable to restore original file from backup file \"" % backupPath +
"\" after failure.").data());
123 void createBackupFile(
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream)
127 #ifndef PLATFORM_WINDOWS 128 struct stat backupStat;
130 for(
unsigned int i = 0; ; ++i) {
131 if(backupDir.empty()) {
133 backupPath = originalPath %
'.' % i +
".bak";
135 backupPath = originalPath +
".bak";
138 const string fileName = BasicFileInfo::fileName(originalPath, i);
140 const string ext = BasicFileInfo::extension(originalPath);
141 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
143 backupPath = BasicFileInfo::containingDirectory(originalPath);
145 backupPath += backupDir;
147 backupPath += fileName;
149 backupPath += numberToString(i);
153 backupPath = backupDir;
155 backupPath += fileName;
157 backupPath += numberToString(i);
161 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
163 backupPath = BasicFileInfo::containingDirectory(originalPath);
165 backupPath += backupDir;
167 backupPath += fileName;
170 backupPath = backupDir;
172 backupPath += fileName;
178 #ifdef PLATFORM_WINDOWS 179 if(GetFileAttributes(backupPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
181 if(stat(backupPath.c_str(), &backupStat)) {
188 if(originalStream.is_open()) {
189 originalStream.close();
192 if(std::rename(originalPath.c_str(), backupPath.c_str()) != 0) {
195 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
196 originalStream.exceptions(ios_base::failbit | ios_base::badbit);
198 if(backupStream.is_open()) {
199 backupStream.close();
201 backupStream.open(backupPath, ios_base::out | ios_base::binary);
203 originalStream.open(originalPath, ios_base::in | ios_base::binary);
205 backupStream << originalStream.rdbuf();
210 throwIoFailure(
"Unable to rename original file before rewriting it.");
215 if(originalStream.is_open()) {
216 originalStream.close();
219 if(backupStream.is_open()) {
220 backupStream.close();
223 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
224 backupStream.open(backupPath, ios_base::in | ios_base::binary);
229 if(std::rename(backupPath.c_str(), originalPath.c_str()) != 0) {
230 throwIoFailure((
"Unable to restore original file from backup file \"" % backupPath +
"\" after failure.").data());
232 throwIoFailure(
"Unable to open backup file.");
266 if(!backupPath.empty()) {
268 fileInfo.
addNotification(NotificationType::Information,
"Rewriting the file to apply changed tag information has been aborted.", context);
271 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
273 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
276 fileInfo.
addNotification(NotificationType::Information,
"Applying new tag information has been aborted.", context);
281 if(!backupPath.empty()) {
283 fileInfo.
addNotification(NotificationType::Critical,
"Rewriting the file to apply changed tag information failed.", context);
286 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
288 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
291 fileInfo.
addNotification(NotificationType::Critical,
"Applying new tag information failed.", context);
296 const char *what = catchIoFailure();
297 if(!backupPath.empty()) {
299 fileInfo.
addNotification(NotificationType::Critical,
"An IO error occured when rewriting the file to apply changed tag information.", context);
302 fileInfo.
addNotification(NotificationType::Information,
"The original file has been restored.", context);
304 fileInfo.
addNotification(NotificationType::Critical, catchIoFailure(), context);
307 fileInfo.
addNotification(NotificationType::Critical,
"An IO error occured when applying tag information.", context);
309 throwIoFailure(what);
Contains utility classes helping to read and write streams.