summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
Diffstat (limited to 'zen')
-rwxr-xr-xzen/file_access.cpp54
-rwxr-xr-xzen/string_base.h16
-rwxr-xr-xzen/thread.h28
3 files changed, 60 insertions, 38 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 273616e3..b894645c 100755
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -8,11 +8,13 @@
#include <map>
#include <algorithm>
#include <stdexcept>
+#include <chrono>
#include "file_traverser.h"
#include "scope_guard.h"
#include "symlink_target.h"
#include "file_id_def.h"
#include "file_io.h"
+#include "crc.h"
#include <sys/vfs.h> //statfs
#include <sys/time.h> //lutimes
@@ -282,6 +284,7 @@ void zen::removeDirectoryPlainRecursion(const Zstring& dirPath) //throw FileErro
namespace
{
+
/* Usage overview: (avoid circular pattern!)
renameFile() --> renameFile_sub()
@@ -336,6 +339,25 @@ void zen::renameFile(const Zstring& pathSource, const Zstring& pathTarget) //thr
}
catch (ErrorTargetExisting&)
{
+#if 0 //"Work around pen drive failing to change file name case" => enable if needed: https://www.freefilesync.org/forum/viewtopic.php?t=4279
+ const Zstring fileNameSrc = afterLast (pathSource, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
+ const Zstring fileNameTrg = afterLast (pathTarget, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
+ const Zstring parentPathSrc = beforeLast(pathSource, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
+ const Zstring parentPathTrg = beforeLast(pathTarget, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE);
+ //some (broken) devices may fail to rename case directly:
+ if (equalFilePath(parentPathSrc, parentPathTrg))
+ {
+ if (fileNameSrc == fileNameTrg)
+ return; //non-sensical request
+
+ const Zstring tempFilePath = getTemporaryPath8Dot3(pathSource); //throw FileError
+ renameFile_sub(pathSource, tempFilePath); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
+ ZEN_ON_SCOPE_FAIL(renameFile_sub(tempFilePath, pathSource)); //"try" our best to be "atomic" :>
+ renameFile_sub(tempFilePath, pathTarget); //throw FileError, ErrorDifferentVolume, ErrorTargetExisting
+ return;
+ }
+#endif
+
throw;
}
}
@@ -385,7 +407,7 @@ void setWriteTimeNative(const Zstring& itemPath, const struct ::timespec& modTim
}
-warn_static("remove after test")
+
void zen::setFileTime(const Zstring& filePath, int64_t modTime, ProcSymlink procSl) //throw FileError
{
struct ::timespec writeTime = {};
@@ -628,27 +650,27 @@ FileCopyResult copyFileOsSpecific(const Zstring& sourceFile, //throw FileError,
//close output file handle before setting file time; also good place to catch errors when closing stream!
fileOut.finalize(); //throw FileError, (X) essentially a close() since buffers were already flushed
-Opt<FileError> errorModTime;
- try
- {
- //we cannot set the target file times (::futimes) while the file descriptor is still open after a write operation:
- //this triggers bugs on samba shares where the modification time is set to current time instead.
- //Linux: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340236
- // http://comments.gmane.org/gmane.linux.file-systems.cifs/2854
- //OS X: http://www.freefilesync.org/forum/viewtopic.php?t=356
- setWriteTimeNative(targetFile, sourceInfo.st_mtim, ProcSymlink::FOLLOW); //throw FileError
- }
- catch (const FileError& e)
- {
- errorModTime = FileError(e.toString()); //avoid slicing
- }
+ Opt<FileError> errorModTime;
+ try
+ {
+ //we cannot set the target file times (::futimes) while the file descriptor is still open after a write operation:
+ //this triggers bugs on samba shares where the modification time is set to current time instead.
+ //Linux: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340236
+ // http://comments.gmane.org/gmane.linux.file-systems.cifs/2854
+ //OS X: http://www.freefilesync.org/forum/viewtopic.php?t=356
+ setWriteTimeNative(targetFile, sourceInfo.st_mtim, ProcSymlink::FOLLOW); //throw FileError
+ }
+ catch (const FileError& e)
+ {
+ errorModTime = FileError(e.toString()); //avoid slicing
+ }
FileCopyResult result;
result.fileSize = sourceInfo.st_size;
result.modTime = sourceInfo.st_mtim.tv_sec; //
result.sourceFileId = extractFileId(sourceInfo);
result.targetFileId = extractFileId(targetInfo);
- result.errorModTime = errorModTime;
+ result.errorModTime = errorModTime;
return result;
}
diff --git a/zen/string_base.h b/zen/string_base.h
index 2ec2e894..cb7ced20 100755
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -573,14 +573,14 @@ template <class InputIterator> inline
Zbase<Char, SP>& Zbase<Char, SP>::append(InputIterator first, InputIterator last)
{
const size_t len = std::distance(first, last);
- if (len > 0) //avoid making this string unshared for no reason
- {
- const size_t thisLen = length();
- reserve(thisLen + len); //make unshared and check capacity
-
- *std::copy(first, last, rawStr_ + thisLen) = 0;
- this->setLength(rawStr_, thisLen + len);
- }
+ if (len > 0) //avoid making this string unshared for no reason
+ {
+ const size_t thisLen = length();
+ reserve(thisLen + len); //make unshared and check capacity
+
+ *std::copy(first, last, rawStr_ + thisLen) = 0;
+ this->setLength(rawStr_, thisLen + len);
+ }
return *this;
}
diff --git a/zen/thread.h b/zen/thread.h
index 76306a51..41261f1e 100755
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -194,38 +194,38 @@ public:
void reportFinished(Opt<T>&& result)
{
{
- std::lock_guard<std::mutex> dummy(lockResult);
- ++jobsFinished;
+ std::lock_guard<std::mutex> dummy(lockResult_);
+ ++jobsFinished_;
if (!result_)
result_ = std::move(result);
}
- conditionJobDone.notify_all(); //better notify all, considering bugs like: https://svn.boost.org/trac/boost/ticket/7796
+ conditionJobDone_.notify_all(); //better notify all, considering bugs like: https://svn.boost.org/trac/boost/ticket/7796
}
//context: main thread
template <class Duration>
bool waitForResult(size_t jobsTotal, const Duration& duration)
{
- std::unique_lock<std::mutex> dummy(lockResult);
- return conditionJobDone.wait_for(dummy, duration, [&] { return this->jobDone(jobsTotal); });
+ std::unique_lock<std::mutex> dummy(lockResult_);
+ return conditionJobDone_.wait_for(dummy, duration, [&] { return this->jobDone(jobsTotal); });
}
Opt<T> getResult(size_t jobsTotal)
{
- std::unique_lock<std::mutex> dummy(lockResult);
- conditionJobDone.wait(dummy, [&] { return this->jobDone(jobsTotal); });
+ std::unique_lock<std::mutex> dummy(lockResult_);
+ conditionJobDone_.wait(dummy, [&] { return this->jobDone(jobsTotal); });
return std::move(result_);
}
private:
- bool jobDone(size_t jobsTotal) const { return result_ || (jobsFinished >= jobsTotal); } //call while locked!
+ bool jobDone(size_t jobsTotal) const { return result_ || (jobsFinished_ >= jobsTotal); } //call while locked!
- std::mutex lockResult;
- size_t jobsFinished = 0; //
- Opt<T> result_; //our condition is: "have result" or "jobsFinished == jobsTotal"
- std::condition_variable conditionJobDone;
+ std::mutex lockResult_;
+ size_t jobsFinished_ = 0; //
+ Opt<T> result_; //our condition is: "have result" or "jobsFinished_ == jobsTotal"
+ std::condition_variable conditionJobDone_;
};
@@ -379,8 +379,8 @@ InterruptibleThread::InterruptibleThread(Function&& f) : intStatus_(std::make_sh
threadCompleted_ = pFinished.get_future();
stdThread_ = std::thread([f = std::forward<Function>(f),
- intStatus = this->intStatus_,
- pFinished = std::move(pFinished)]() mutable
+ intStatus = this->intStatus_,
+ pFinished = std::move(pFinished)]() mutable
{
assert(!impl::refThreadLocalInterruptionStatus());
impl::refThreadLocalInterruptionStatus() = intStatus.get();
bgstack15