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;
67 if(originalStream.is_open()) {
68 originalStream.close();
71 backupStream.exceptions(ios_base::goodbit);
74 backupStream.open(backupPath, ios_base::in | ios_base::binary);
75 if(backupStream.is_open()) {
78 throwIoFailure(
"Backup/temporary file has not been created.");
81 std::remove(originalPath.c_str());
82 if(std::rename(backupPath.c_str(), originalPath.c_str()) != 0) {
86 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
87 originalStream.exceptions(ios_base::failbit | ios_base::badbit);
88 backupStream.open(backupPath, ios_base::in | ios_base::binary);
89 originalStream.open(originalPath, ios_base::out | ios_base::binary);
90 originalStream << backupStream.rdbuf();
94 throwIoFailure((
"Unable to restore original file from backup file \"" % backupPath +
"\" after failure.").data());
121 void createBackupFile(
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream)
125 #ifndef PLATFORM_WINDOWS 126 struct stat backupStat;
128 for(
unsigned int i = 0; ; ++i) {
129 if(backupDir.empty()) {
131 backupPath = originalPath %
'.' % i +
".bak";
133 backupPath = originalPath +
".bak";
136 const string fileName = BasicFileInfo::fileName(originalPath, i);
138 const string ext = BasicFileInfo::extension(originalPath);
139 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
141 backupPath = BasicFileInfo::containingDirectory(originalPath);
143 backupPath += backupDir;
145 backupPath += fileName;
147 backupPath += numberToString(i);
151 backupPath = backupDir;
153 backupPath += fileName;
155 backupPath += numberToString(i);
159 if(backupDir.at(0) !=
'/' && (backupDir.size() < 2 || backupDir.at(1) !=
':')) {
161 backupPath = BasicFileInfo::containingDirectory(originalPath);
163 backupPath += backupDir;
165 backupPath += fileName;
168 backupPath = backupDir;
170 backupPath += fileName;
176 #ifdef PLATFORM_WINDOWS 177 if(GetFileAttributes(backupPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
179 if(stat(backupPath.c_str(), &backupStat)) {
186 std::remove(backupPath.c_str());
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.