summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
Diffstat (limited to 'zen')
-rw-r--r--zen/assert_static.h4
-rw-r--r--zen/file_handling.cpp139
-rw-r--r--zen/file_handling.h49
-rw-r--r--zen/file_traverser.cpp2
-rw-r--r--zen/osx_throw_exception.h4
-rw-r--r--zen/recycler.cpp27
-rw-r--r--zen/recycler.h12
-rw-r--r--zen/scope_guard.h4
-rw-r--r--zen/stl_tools.h4
-rw-r--r--zen/string_base.h8
-rw-r--r--zen/string_tools.h4
-rw-r--r--zen/string_traits.h4
-rw-r--r--zen/type_tools.h4
-rw-r--r--zen/type_traits.h4
-rw-r--r--zen/utf.h4
15 files changed, 136 insertions, 137 deletions
diff --git a/zen/assert_static.h b/zen/assert_static.h
index 469e0299..17d5c370 100644
--- a/zen/assert_static.h
+++ b/zen/assert_static.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp
index 621c2b1b..8c5584db 100644
--- a/zen/file_handling.cpp
+++ b/zen/file_handling.cpp
@@ -511,7 +511,9 @@ private:
};
-void removeDirectoryImpl(const Zstring& directory, CallbackRemoveDir* callback) //throw FileError
+void removeDirectoryImpl(const Zstring& directory, //throw FileError
+ const std::function<void (const Zstring& filename)>& onBeforeFileDeletion,
+ const std::function<void (const Zstring& dirname)>& onBeforeDirDeletion)
{
assert(somethingExists(directory)); //[!]
@@ -525,7 +527,8 @@ void removeDirectoryImpl(const Zstring& directory, CallbackRemoveDir* callback)
//attention: check if directory is a symlink! Do NOT traverse into it deleting contained files!!!
if (symlinkExists(directory)) //remove symlink directly
{
- if (callback) callback->onBeforeDirDeletion(directory); //once per symlink
+ if (onBeforeDirDeletion)
+ onBeforeDirDeletion(directory); //once per symlink
#ifdef ZEN_WIN
const wchar_t functionName[] = L"RemoveDirectory";
if (!::RemoveDirectory(directoryFmt.c_str()))
@@ -546,22 +549,20 @@ void removeDirectoryImpl(const Zstring& directory, CallbackRemoveDir* callback)
}
//delete directories recursively
- std::for_each(dirList.begin(), dirList.end(),
- [&](const Zstring& dirname)
- {
- removeDirectoryImpl(dirname, callback); //throw FileError; call recursively to correctly handle symbolic links
- });
+ for (const Zstring& dirname : dirList)
+ removeDirectoryImpl(dirname, onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError; call recursively to correctly handle symbolic links
//delete files
- std::for_each(fileList.begin(), fileList.end(),
- [&](const Zstring& filename)
+ for (const Zstring& filename : fileList)
{
- if (callback) callback->onBeforeFileDeletion(filename); //call once per file
+ if (onBeforeFileDeletion)
+ onBeforeFileDeletion(filename); //call once per file
removeFile(filename); //throw FileError
- });
+ }
//parent directory is deleted last
- if (callback) callback->onBeforeDirDeletion(directory); //and once per folder
+ if (onBeforeDirDeletion)
+ onBeforeDirDeletion(directory); //and once per folder
#ifdef ZEN_WIN
const wchar_t functionName[] = L"RemoveDirectory";
if (!::RemoveDirectory(directoryFmt.c_str()))
@@ -647,7 +648,7 @@ void setFileTimeRaw(const Zstring& filename, const FILETIME& creationTime, const
nullptr,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory
- (procSl == SYMLINK_DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0), //process symlinks
+ (procSl == ProcSymlink::DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0), //process symlinks
nullptr);
};
@@ -805,7 +806,7 @@ void setFileTimeRaw(const Zstring& filename, const FILETIME& creationTime, const
nullptr,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory
- (procSl == SYMLINK_DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0),
+ (procSl == ProcSymlink::DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0),
nullptr);
assert(hFile != INVALID_HANDLE_VALUE);
ZEN_ON_SCOPE_EXIT(::CloseHandle(hFile));
@@ -823,12 +824,14 @@ void setFileTimeRaw(const Zstring& filename, const FILETIME& creationTime, const
}
-void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback)
+void zen::removeDirectory(const Zstring& directory, //throw FileError
+ const std::function<void (const Zstring& filename)>& onBeforeFileDeletion,
+ const std::function<void (const Zstring& dirname)>& onBeforeDirDeletion)
{
//no error situation if directory is not existing! manual deletion relies on it!
if (!somethingExists(directory))
return; //neither directory nor any other object (e.g. broken symlink) with that name existing
- removeDirectoryImpl(directory, callback);
+ removeDirectoryImpl(directory, onBeforeFileDeletion, onBeforeDirDeletion);
}
@@ -865,7 +868,7 @@ void zen::setFileTime(const Zstring& filename, const Int64& modTime, ProcSymlink
newTimes[0].tv_sec = ::time(nullptr); //access time (seconds)
newTimes[1].tv_sec = to<time_t>(modTime); //modification time (seconds)
- const int rv = procSl == SYMLINK_FOLLOW ?
+ const int rv = procSl == ProcSymlink::FOLLOW ?
:: utimes(filename.c_str(), newTimes) : //utimensat() not yet implemented on OS X
::lutimes(filename.c_str(), newTimes);
if (rv != 0)
@@ -960,8 +963,8 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym
//CAVEAT: if a file system does not support ACLs, GetFileSecurity() will return successfully with a *valid* security descriptor containing *no* ACL entries!
//NOTE: ::GetFileSecurity()/::SetFileSecurity() do NOT follow Symlinks! getResolvedFilePath() requires Vista or later!
- const Zstring sourceResolved = procSl == SYMLINK_FOLLOW && symlinkExists(source) ? getResolvedFilePath(source) : source; //throw FileError
- const Zstring targetResolved = procSl == SYMLINK_FOLLOW && symlinkExists(target) ? getResolvedFilePath(target) : target; //
+ const Zstring sourceResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(source) ? getResolvedFilePath(source) : source; //throw FileError
+ const Zstring targetResolved = procSl == ProcSymlink::FOLLOW && symlinkExists(target) ? getResolvedFilePath(target) : target; //
//setting privileges requires admin rights!
try
@@ -1111,7 +1114,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym
#endif
struct stat fileInfo = {};
- if (procSl == SYMLINK_FOLLOW)
+ if (procSl == ProcSymlink::FOLLOW)
{
if (::stat(source.c_str(), &fileInfo) != 0)
throw FileError(replaceCpy(_("Cannot read permissions of %x."), L"%x", fmtFileName(source)), formatSystemError(L"stat", getLastError()));
@@ -1339,7 +1342,7 @@ void zen::makeDirectoryPlain(const Zstring& directory, //throw FileError, ErrorT
//enforce copying file permissions: it's advertized on GUI...
if (copyFilePermissions)
- copyObjectPermissions(templateDir, directory, SYMLINK_FOLLOW); //throw FileError
+ copyObjectPermissions(templateDir, directory, ProcSymlink::FOLLOW); //throw FileError
guardNewDir.dismiss(); //target has been created successfully!
}
@@ -1397,18 +1400,18 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool
&sourceAttr)) //__out LPVOID lpFileInformation
throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(sourceLink)), formatSystemError(L"GetFileAttributesEx", getLastError()));
- setFileTimeRaw(targetLink, sourceAttr.ftCreationTime, sourceAttr.ftLastWriteTime, SYMLINK_DIRECT); //throw FileError
+ setFileTimeRaw(targetLink, sourceAttr.ftCreationTime, sourceAttr.ftLastWriteTime, ProcSymlink::DIRECT); //throw FileError
#elif defined ZEN_LINUX || defined ZEN_MAC
struct ::stat srcInfo = {};
if (::lstat(sourceLink.c_str(), &srcInfo) != 0)
throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(sourceLink)), formatSystemError(L"lstat", getLastError()));
- setFileTime(targetLink, Int64(srcInfo.st_mtime), SYMLINK_DIRECT); //throw FileError
+ setFileTime(targetLink, Int64(srcInfo.st_mtime), ProcSymlink::DIRECT); //throw FileError
#endif
if (copyFilePermissions)
- copyObjectPermissions(sourceLink, targetLink, SYMLINK_DIRECT); //throw FileError
+ copyObjectPermissions(sourceLink, targetLink, ProcSymlink::DIRECT); //throw FileError
guardNewLink.dismiss(); //target has been created successfully!
}
@@ -1516,7 +1519,7 @@ bool canCopyAsSparse(const Zstring& sourceFile, const Zstring& targetFile) //thr
//precondition: canCopyAsSparse() must return "true"!
void copyFileWindowsSparse(const Zstring& sourceFile,
const Zstring& targetFile,
- CallbackCopyFile* callback,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
{
assert(canCopyAsSparse(sourceFile, targetFile));
@@ -1701,8 +1704,8 @@ void copyFileWindowsSparse(const Zstring& sourceFile,
//total bytes transferred may be larger than file size! context information + ADS or smaller (sparse, compressed)!
//invoke callback method to update progress indicators
- if (callback)
- callback->updateCopyStatus(Int64(bytesRead)); //throw X!
+ if (onUpdateCopyStatus)
+ onUpdateCopyStatus(Int64(bytesRead)); //throw X!
if (bytesRead > 0)
someBytesWritten = true;
@@ -1764,12 +1767,12 @@ DEFINE_NEW_FILE_ERROR(ErrorShouldCopyAsSparse);
class ErrorHandling
{
public:
- ErrorHandling() : shouldCopyAsSparse(false), exceptionInUserCallback(nullptr) {}
+ ErrorHandling() : shouldCopyAsSparse(false) {}
//call context: copyCallbackInternal()
void reportErrorShouldCopyAsSparse() { shouldCopyAsSparse = true; }
- void reportUserException(CallbackCopyFile& userCallback) { exceptionInUserCallback = &userCallback; }
+ void reportUserException(const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus) { exceptionInUserCallback = onUpdateCopyStatus; }
void reportError(const std::wstring& msg, const std::wstring& description) { errorMsg = std::make_pair(msg, description); }
@@ -1780,7 +1783,12 @@ public:
throw ErrorShouldCopyAsSparse(L"sparse dummy value");
if (exceptionInUserCallback)
- exceptionInUserCallback->updateCopyStatus(0); //rethrow (hopefully!)
+ try
+ {
+ exceptionInUserCallback(0); //should throw again!!!
+ assert(false);
+ }
+ catch (...) { throw; }
if (!errorMsg.first.empty())
throw FileError(errorMsg.first, errorMsg.second);
@@ -1789,25 +1797,25 @@ public:
private:
bool shouldCopyAsSparse; //
std::pair<std::wstring, std::wstring> errorMsg; //these are exclusive!
- CallbackCopyFile* exceptionInUserCallback; //
+ std::function<void(Int64 bytesDelta)> exceptionInUserCallback; // -> optional
};
struct CallbackData
{
- CallbackData(CallbackCopyFile* cb, //may be nullptr
+ CallbackData(const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
const Zstring& sourceFile,
const Zstring& targetFile) :
sourceFile_(sourceFile),
targetFile_(targetFile),
- userCallback(cb),
+ onUpdateCopyStatus_(onUpdateCopyStatus),
fileInfoSrc(),
fileInfoTrg() {}
const Zstring& sourceFile_;
const Zstring& targetFile_;
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus_;
- CallbackCopyFile* const userCallback; //optional!
ErrorHandling errorHandler;
BY_HANDLE_FILE_INFORMATION fileInfoSrc; //modified by CopyFileEx() at beginning
BY_HANDLE_FILE_INFORMATION fileInfoTrg; //
@@ -1899,18 +1907,17 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize,
//called after copy operation is finished - note: for 0-sized files this callback is invoked just ONCE!
//if (totalFileSize.QuadPart == totalBytesTransferred.QuadPart && dwStreamNumber == 1) {}
- if (cbd.userCallback &&
- totalBytesTransferred.QuadPart >= 0) //should be always true, but let's still check
+ if (cbd.onUpdateCopyStatus_ && totalBytesTransferred.QuadPart >= 0) //should be always true, but let's still check
try
{
- cbd.userCallback->updateCopyStatus(totalBytesTransferred.QuadPart - cbd.bytesReported); //throw X!
+ cbd.onUpdateCopyStatus_(totalBytesTransferred.QuadPart - cbd.bytesReported); //throw X!
cbd.bytesReported = totalBytesTransferred.QuadPart;
}
catch (...)
{
//#warning migrate to std::exception_ptr when available
- cbd.errorHandler.reportUserException(*cbd.userCallback);
+ cbd.errorHandler.reportUserException(cbd.onUpdateCopyStatus_);
return PROGRESS_CANCEL;
}
return PROGRESS_CONTINUE;
@@ -1924,7 +1931,7 @@ const bool supportNonEncryptedDestination = winXpOrLater(); //encrypted destinat
void copyFileWindowsDefault(const Zstring& sourceFile,
const Zstring& targetFile,
- CallbackCopyFile* callback,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked, ErrorShouldCopyAsSparse
{
//try to get backup read and write privileges: who knows, maybe this helps solve some obscure "access denied" errors
@@ -1947,7 +1954,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile,
//documentation on CopyFile2() even states: "It is not recommended to pause copies that are using this flag." How dangerous is this thing, why offer it at all???
//perf advantage: ~15% faster
- CallbackData cbd(callback, sourceFile, targetFile);
+ CallbackData cbd(onUpdateCopyStatus, sourceFile, targetFile);
const bool success = ::CopyFileEx( //same performance like CopyFile()
applyLongPathPrefix(sourceFile).c_str(), //__in LPCTSTR lpExistingFileName,
@@ -2051,7 +2058,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile,
}
//####################################### DST hack ###########################################
- setFileTimeRaw(targetFile, creationTimeOut, lastWriteTimeOut, SYMLINK_FOLLOW); //throw FileError
+ setFileTimeRaw(targetFile, creationTimeOut, lastWriteTimeOut, ProcSymlink::FOLLOW); //throw FileError
}
guardTarget.dismiss(); //target has been created successfully!
@@ -2060,26 +2067,29 @@ void copyFileWindowsDefault(const Zstring& sourceFile,
//another layer to support copying sparse files
inline
-void copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Zstring& targetFile, CallbackCopyFile* callback, InSyncAttributes* sourceAttr)
+void copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus, InSyncAttributes* sourceAttr)
{
try
{
- copyFileWindowsDefault(sourceFile, targetFile, callback, sourceAttr); //throw ErrorShouldCopyAsSparse et al.
+ copyFileWindowsDefault(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw ErrorShouldCopyAsSparse et al.
}
catch (ErrorShouldCopyAsSparse&) //we cheaply check for this condition within callback of ::CopyFileEx()!
{
- copyFileWindowsSparse(sourceFile, targetFile, callback, sourceAttr);
+ copyFileWindowsSparse(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr);
}
}
//another layer of indirection solving 8.3 name clashes
inline
-void copyFileWindows(const Zstring& sourceFile, const Zstring& targetFile, CallbackCopyFile* callback, InSyncAttributes* sourceAttr)
+void copyFileWindows(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
+ InSyncAttributes* sourceAttr)
{
try
{
- copyFileWindowsSelectRoutine(sourceFile, targetFile, callback, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
}
catch (const ErrorTargetExisting&)
{
@@ -2087,7 +2097,7 @@ void copyFileWindows(const Zstring& sourceFile, const Zstring& targetFile, Callb
if (have8dot3NameClash(targetFile))
{
Fix8Dot3NameClash dummy(targetFile); //throw FileError; move clashing filename to the side
- copyFileWindowsSelectRoutine(sourceFile, targetFile, callback, sourceAttr); //throw FileError; the short filename name clash is solved, this should work now
+ copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError; the short filename name clash is solved, this should work now
return;
}
throw;
@@ -2098,7 +2108,7 @@ void copyFileWindows(const Zstring& sourceFile, const Zstring& targetFile, Callb
#elif defined ZEN_LINUX || defined ZEN_MAC
void copyFileLinuxMac(const Zstring& sourceFile,
const Zstring& targetFile,
- CallbackCopyFile* callback,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
{
//open sourceFile for reading
@@ -2123,8 +2133,8 @@ void copyFileLinuxMac(const Zstring& sourceFile,
fileOut.write(&buffer[0], bytesRead); //throw FileError
//invoke callback method to update progress indicators
- if (callback)
- callback->updateCopyStatus(Int64(bytesRead)); //throw X!
+ if (onUpdateCopyStatus)
+ onUpdateCopyStatus(Int64(bytesRead)); //throw X!
}
while (!fileIn.eof());
@@ -2155,7 +2165,7 @@ void copyFileLinuxMac(const Zstring& sourceFile,
//http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340236
//http://comments.gmane.org/gmane.linux.file-systems.cifs/2854
//on the other hand we thereby have to reopen https://sourceforge.net/p/freefilesync/bugs/230/
- setFileTime(targetFile, sourceInfo.st_mtime, SYMLINK_FOLLOW); //throw FileError
+ setFileTime(targetFile, sourceInfo.st_mtime, ProcSymlink::FOLLOW); //throw FileError
guardTarget.dismiss(); //target has been created successfully!
}
@@ -2190,13 +2200,16 @@ copyFileWindowsDefault(::CopyFileEx) copyFileWindowsSparse(::BackupRead/::Backu
*/
inline
-void copyFileSelectOs(const Zstring& sourceFile, const Zstring& targetFile, CallbackCopyFile* callback, InSyncAttributes* sourceAttr)
+void copyFileSelectOs(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
+ InSyncAttributes* sourceAttr)
{
#ifdef ZEN_WIN
- copyFileWindows(sourceFile, targetFile, callback, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ copyFileWindows(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
#elif defined ZEN_LINUX || defined ZEN_MAC
- copyFileLinuxMac(sourceFile, targetFile, callback, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
+ copyFileLinuxMac(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
#endif
}
}
@@ -2206,7 +2219,8 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
const Zstring& targetFile,
bool copyFilePermissions,
bool transactionalCopy,
- CallbackCopyFile* callback,
+ const std::function<void()>& onDeleteTargetFile,
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus,
InSyncAttributes* sourceAttr)
{
if (transactionalCopy)
@@ -2216,7 +2230,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
//raw file copy
try
{
- copyFileSelectOs(sourceFile, temporary, callback, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ copyFileSelectOs(sourceFile, temporary, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
}
catch (ErrorTargetExisting&)
{
@@ -2225,15 +2239,15 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
temporary = findUnusedTempName(targetFile);
//retry
- copyFileSelectOs(sourceFile, temporary, callback, sourceAttr); //throw FileError
+ copyFileSelectOs(sourceFile, temporary, onUpdateCopyStatus, sourceAttr); //throw FileError
}
//transactional behavior: ensure cleanup; not needed before copyFileSelectOs() which is already transactional
zen::ScopeGuard guardTempFile = zen::makeGuard([&] { try { removeFile(temporary); } catch (FileError&) {} });
//have target file deleted (after read access on source and target has been confirmed) => allow for almost transactional overwrite
- if (callback)
- callback->deleteTargetFile(targetFile); //throw X
+ if (onDeleteTargetFile)
+ onDeleteTargetFile(); //throw X
//rename temporary file:
//perf: this call is REALLY expensive on unbuffered volumes! ~40% performance decrease on FAT USB stick!
@@ -2264,9 +2278,10 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
}
else
{
- if (callback) callback->deleteTargetFile(targetFile);
+ if (onDeleteTargetFile)
+ onDeleteTargetFile();
- copyFileSelectOs(sourceFile, targetFile, callback, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ copyFileSelectOs(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
}
/*
Note: non-transactional file copy solves at least four problems:
@@ -2281,7 +2296,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath
{
zen::ScopeGuard guardTargetFile = zen::makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {}});
- copyObjectPermissions(sourceFile, targetFile, SYMLINK_FOLLOW); //throw FileError
+ copyObjectPermissions(sourceFile, targetFile, ProcSymlink::FOLLOW); //throw FileError
guardTargetFile.dismiss(); //target has been created successfully!
}
diff --git a/zen/file_handling.h b/zen/file_handling.h
index b3d5ca1a..48a762d7 100644
--- a/zen/file_handling.h
+++ b/zen/file_handling.h
@@ -7,6 +7,7 @@
#ifndef FILE_HANDLING_H_8017341345614857
#define FILE_HANDLING_H_8017341345614857
+#include <functional>
#include "zstring.h"
#include "file_error.h"
#include "file_id_def.h"
@@ -14,19 +15,15 @@
namespace zen
{
-struct CallbackRemoveDir;
-struct CallbackCopyFile;
-
-
bool fileExists (const Zstring& filename); //noexcept; check whether file or file-symlink exists
bool dirExists (const Zstring& dirname ); //noexcept; check whether directory or dir-symlink exists
bool symlinkExists (const Zstring& linkname); //noexcept; check whether a symbolic link exists
bool somethingExists(const Zstring& objname ); //noexcept; check whether any object with this name exists
-enum ProcSymlink
+enum class ProcSymlink
{
- SYMLINK_DIRECT,
- SYMLINK_FOLLOW
+ DIRECT,
+ FOLLOW
};
void setFileTime(const Zstring& filename, const Int64& modificationTime, ProcSymlink procSl); //throw FileError
@@ -37,7 +34,9 @@ UInt64 getFreeDiskSpace(const Zstring& path); //throw FileError
//file handling
bool removeFile(const Zstring& filename); //throw FileError; return "false" if file is not existing
-void removeDirectory(const Zstring& directory, CallbackRemoveDir* callback = nullptr); //throw FileError
+void removeDirectory(const Zstring& directory, //throw FileError
+ const std::function<void (const Zstring& filename)>& onBeforeFileDeletion = nullptr, //optional;
+ const std::function<void (const Zstring& dirname)>& onBeforeDirDeletion = nullptr); //one call for each *existing* object!
//rename file or directory: no copying!!!
void renameFile(const Zstring& oldName, const Zstring& newName); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
@@ -64,37 +63,21 @@ void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissi
const Zstring& targetFile, //symlink handling: dereference source
bool copyFilePermissions,
bool transactionalCopy,
- CallbackCopyFile* callback, //may be nullptr
+ //if target is existing user needs to implement deletion: copyFile() NEVER overwrites target if already existing!
+ //if transactionalCopy == true, full read access on source had been proven at this point, so it's safe to delete it.
+ const std::function<void()>& onDeleteTargetFile, //may be nullptr; throw X!
+ //Linux: unconditionally
+ //Windows: first exception is swallowed, updateCopyStatus() is then called again where it should throw again and the exception will propagate as expected
+ //accummulated delta != file size! consider ADS, sparse, compressed files
+ const std::function<void(Int64 bytesDelta)>& onUpdateCopyStatus, //may be nullptr; throw X!
+
InSyncAttributes* newAttrib = nullptr); //return current attributes at the time of copy
+
//Note: it MAY happen that copyFile() leaves temp files behind, e.g. temporary network drop.
// => clean them up at an appropriate time (automatically set sync directions to delete them). They have the following ending:
const Zstring TEMP_FILE_ENDING = Zstr(".ffs_tmp");
void copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions); //throw FileError
-
-
-
-//----------- callbacks ---------------
-struct CallbackRemoveDir
-{
- virtual ~CallbackRemoveDir() {}
- virtual void onBeforeFileDeletion(const Zstring& filename) = 0; //one call for each *existing* object!
- virtual void onBeforeDirDeletion (const Zstring& dirname ) = 0; //
-};
-
-struct CallbackCopyFile
-{
- virtual ~CallbackCopyFile() {}
-
- //if target is existing user needs to implement deletion: copyFile() NEVER overwrites target if already existing!
- //if transactionalCopy == true, full read access on source had been proven at this point, so it's safe to delete it.
- virtual void deleteTargetFile(const Zstring& targetFile) = 0; //may throw exceptions
-
- //may throw:
- //Linux: unconditionally
- //Windows: first exception is swallowed, updateCopyStatus() is then called again where it should throw again and the exception will propagate as expected
- virtual void updateCopyStatus(Int64 bytesDelta) = 0; //accummulated delta != file size! consider ADS, sparse, compressed files
-};
}
#endif //FILE_HANDLING_H_8017341345614857
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index 0e06d6c5..9c1b01a4 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -452,7 +452,7 @@ private:
try
{
//set modification time including DST hack: this function is too clever to not introduce this dependency
- setFileTime(it->first, it->second, SYMLINK_FOLLOW); //throw FileError
+ setFileTime(it->first, it->second, ProcSymlink::FOLLOW); //throw FileError
}
catch (FileError&)
{
diff --git a/zen/osx_throw_exception.h b/zen/osx_throw_exception.h
index 018e9456..07e3af3e 100644
--- a/zen/osx_throw_exception.h
+++ b/zen/osx_throw_exception.h
@@ -35,9 +35,9 @@ inline
void throwSysError(NSException* e) //throw SysError
{
std::string msg;
-if (const char* name = [[e name ] cStringUsingEncoding:NSUTF8StringEncoding]) //"const char*" NOT owned by us!
+ if (const char* name = [[e name ] cStringUsingEncoding:NSUTF8StringEncoding]) //"const char*" NOT owned by us!
msg += name;
-if (const char* descr = [[e reason] cStringUsingEncoding:NSUTF8StringEncoding])
+ if (const char* descr = [[e reason] cStringUsingEncoding:NSUTF8StringEncoding])
{
msg += "\n";
msg += descr;
diff --git a/zen/recycler.cpp b/zen/recycler.cpp
index a1353f0b..16c2ac11 100644
--- a/zen/recycler.cpp
+++ b/zen/recycler.cpp
@@ -49,22 +49,23 @@ const bool useIFileOperation = vistaOrLater(); //caveat: function scope static i
struct CallbackData
{
- CallbackData(CallbackRecycling* cb) :
- userCallback(cb),
+ CallbackData(const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus) :
+ notifyDeletionStatus_(notifyDeletionStatus),
exceptionInUserCallback(false) {}
- CallbackRecycling* const userCallback; //optional!
+ const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus_; //optional!
bool exceptionInUserCallback;
};
+
bool recyclerCallback(const wchar_t* filename, void* sink)
{
CallbackData& cbd = *static_cast<CallbackData*>(sink); //sink is NOT optional here
- if (cbd.userCallback)
+ if (cbd.notifyDeletionStatus_)
try
{
- cbd.userCallback->updateStatus(filename); //throw ?
+ cbd.notifyDeletionStatus_(filename); //throw ?
}
catch (...)
{
@@ -75,7 +76,7 @@ bool recyclerCallback(const wchar_t* filename, void* sink)
}
}
-void zen::recycleOrDelete(const std::vector<Zstring>& filenames, CallbackRecycling* callback)
+void zen::recycleOrDelete(const std::vector<Zstring>& filenames, const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus)
{
if (filenames.empty())
return;
@@ -95,14 +96,20 @@ void zen::recycleOrDelete(const std::vector<Zstring>& filenames, CallbackRecycli
replaceCpy(_("Cannot load file %x."), L"%x", fmtFileName(getDllName())));
std::vector<const wchar_t*> cNames;
- for (auto it = filenames.begin(); it != filenames.end(); ++it) //CAUTION: to not create temporary strings here!!
+ for (auto it = filenames.begin(); it != filenames.end(); ++it) //CAUTION: do not create temporary strings here!!
cNames.push_back(it->c_str());
- CallbackData cbd(callback);
+ CallbackData cbd(notifyDeletionStatus);
if (!moveToRecycler(&cNames[0], cNames.size(), recyclerCallback, &cbd))
{
- if (cbd.exceptionInUserCallback) //now we may throw...
- callback->updateStatus(Zstring()); //should throw again!
+ if (cbd.exceptionInUserCallback)
+ try
+ {
+ assert(notifyDeletionStatus);
+ notifyDeletionStatus(Zstring()); //should throw again!!!
+ assert(false);
+ }
+ catch (...) { throw; }
std::wstring filenameFmt = fmtFileName(filenames[0]); //probably not the correct file name for file lists larger than 1!
if (filenames.size() > 1)
diff --git a/zen/recycler.h b/zen/recycler.h
index f55971ac..80b31160 100644
--- a/zen/recycler.h
+++ b/zen/recycler.h
@@ -7,6 +7,7 @@
#ifndef RECYCLER_H_INCLUDED
#define RECYCLER_H_INCLUDED
+#include <functional>
#include <vector>
#include <zen/file_error.h>
#include <zen/zstring.h>
@@ -44,16 +45,9 @@ enum StatusRecycler
StatusRecycler recycleBinStatus(const Zstring& pathName); //test existence of Recycle Bin API for certain path
//Win: blocks heavily if recycle bin is really full and drive is slow!!!
-struct CallbackRecycling
-{
- virtual ~CallbackRecycling() {}
-
- //may throw: first exception is swallowed, updateStatus() is then called again where it should throw again and the exception will propagate as expected
- virtual void updateStatus(const Zstring& currentItem) = 0; //currentItem may be empty
-};
-
void recycleOrDelete(const std::vector<Zstring>& filenames, //throw FileError, return "true" if file/dir was actually deleted
- CallbackRecycling* callback); //optional
+ //may throw: first exception is swallowed, updateStatus() is then called again where it should throw again and the exception will propagate as expected
+ const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus); //optional; currentItem may be empty
#endif
}
diff --git a/zen/scope_guard.h b/zen/scope_guard.h
index 000853fd..d48eb922 100644
--- a/zen/scope_guard.h
+++ b/zen/scope_guard.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index bf47bb1c..2bb4fd3f 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/string_base.h b/zen/string_base.h
index 31a09e63..c828b240 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -60,7 +60,7 @@ template <typename Char, //Character Type
*/
template <class Char, //Character Type
- class AP> //Allocator Policy
+ class AP> //Allocator Policy
class StorageDeepCopy : public AP
{
protected:
@@ -113,7 +113,7 @@ private:
template <class Char, //Character Type
- class AP> //Allocator Policy
+ class AP> //Allocator Policy
class StorageRefCountThreadSafe : public AP
{
protected:
@@ -188,8 +188,8 @@ private:
//perf note: interestingly StorageDeepCopy and StorageRefCountThreadSafe show same performance in FFS comparison
template <class Char, //Character Type
- template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy
- class AP = AllocatorOptimalSpeed> //Allocator Policy
+ template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy
+ class AP = AllocatorOptimalSpeed> //Allocator Policy
class Zbase : public SP<Char, AP>
{
public:
diff --git a/zen/string_tools.h b/zen/string_tools.h
index 35e5af2b..1dd5905d 100644
--- a/zen/string_tools.h
+++ b/zen/string_tools.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/string_traits.h b/zen/string_traits.h
index eb79831e..887752c0 100644
--- a/zen/string_traits.h
+++ b/zen/string_traits.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/type_tools.h b/zen/type_tools.h
index 76a12a5a..1f782a2d 100644
--- a/zen/type_tools.h
+++ b/zen/type_tools.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/type_traits.h b/zen/type_traits.h
index a90b9793..b6e05871 100644
--- a/zen/type_traits.h
+++ b/zen/type_traits.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
diff --git a/zen/utf.h b/zen/utf.h
index e428422b..16e543c8 100644
--- a/zen/utf.h
+++ b/zen/utf.h
@@ -1,6 +1,6 @@
// **************************************************************************
-// * This file is part of the zen::Xml project. It is distributed under the *
-// * Boost Software License: http://www.boost.org/LICENSE_1_0.txt *
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
bgstack15