diff options
Diffstat (limited to 'zen')
-rwxr-xr-x | zen/file_access.cpp | 54 | ||||
-rwxr-xr-x | zen/string_base.h | 16 | ||||
-rwxr-xr-x | zen/thread.h | 28 |
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(); |