diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/db_file.cpp | 4 | ||||
-rw-r--r-- | lib/dir_lock.cpp | 2 | ||||
-rw-r--r-- | lib/generate_logfile.h | 14 | ||||
-rw-r--r-- | lib/icon_buffer.cpp | 2 | ||||
-rw-r--r-- | lib/lock_holder.h | 2 | ||||
-rw-r--r-- | lib/parallel_scan.cpp | 6 | ||||
-rw-r--r-- | lib/process_xml.h | 18 | ||||
-rw-r--r-- | lib/resolve_path.cpp | 52 | ||||
-rw-r--r-- | lib/resolve_path.h | 4 | ||||
-rw-r--r-- | lib/return_codes.h | 1 | ||||
-rw-r--r-- | lib/status_handler.h | 4 |
11 files changed, 76 insertions, 33 deletions
diff --git a/lib/db_file.cpp b/lib/db_file.cpp index 8821fc66..53830afe 100644 --- a/lib/db_file.cpp +++ b/lib/db_file.cpp @@ -299,8 +299,8 @@ public: BinStreamIn& in1stPart = has1stPartL ? inL : inR; BinStreamIn& in2ndPart = has1stPartL ? inR : inL; - const size_t size1stPart = readNumber<std::uint64_t>(in1stPart); - const size_t size2ndPart = readNumber<std::uint64_t>(in2ndPart); + const size_t size1stPart = static_cast<size_t>(readNumber<std::uint64_t>(in1stPart)); + const size_t size2ndPart = static_cast<size_t>(readNumber<std::uint64_t>(in2ndPart)); BinaryStream tmpB; tmpB.resize(size1stPart + size2ndPart); diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp index da119f88..bbd97454 100644 --- a/lib/dir_lock.cpp +++ b/lib/dir_lock.cpp @@ -552,7 +552,7 @@ public: ~SharedDirLock() { threadObj.interrupt(); //thread lifetime is subset of this instances's life - threadObj.join(); + threadObj.join(); //we assume precondition "threadObj.joinable()"!!! ::releaseLock(lockfilename_); //throw () } diff --git a/lib/generate_logfile.h b/lib/generate_logfile.h index 651b93cb..beb4f5d3 100644 --- a/lib/generate_logfile.h +++ b/lib/generate_logfile.h @@ -57,7 +57,9 @@ Utf8String generateLogStream_impl(const ErrorLog& log, results.push_back(headerLine); results.push_back(L""); - std::wstring itemsProc = L" " + _("Items processed:") + L" " + toGuiString(itemsSynced); //show always, even if 0! + const wchar_t tabSpace[] = L" "; + + std::wstring itemsProc = tabSpace + _("Items processed:") + L" " + toGuiString(itemsSynced); //show always, even if 0! if (itemsSynced != 0 || dataSynced != 0) //[!] don't show 0 bytes processed if 0 items were processed itemsProc += + L" (" + filesizeToShortString(dataSynced) + L")"; results.push_back(itemsProc); @@ -66,10 +68,10 @@ Utf8String generateLogStream_impl(const ErrorLog& log, { if (itemsSynced != itemsTotal || dataSynced != dataTotal) - results.push_back(L" " + _("Items remaining:") + L" " + toGuiString(itemsTotal - itemsSynced) + L" (" + filesizeToShortString(dataTotal - dataSynced) + L")"); + results.push_back(tabSpace + _("Items remaining:") + L" " + toGuiString(itemsTotal - itemsSynced) + L" (" + filesizeToShortString(dataTotal - dataSynced) + L")"); } - results.push_back(L" " + _("Total time:") + L" " + copyStringTo<std::wstring>(wxTimeSpan::Seconds(totalTime).Format())); + results.push_back(tabSpace + _("Total time:") + L" " + copyStringTo<std::wstring>(wxTimeSpan::Seconds(totalTime).Format())); //calculate max width, this considers UTF-16 only, not true Unicode... size_t sepLineLen = 0; @@ -132,10 +134,10 @@ void saveToLastSyncsLog(const Utf8String& logstream) //throw FileError const size_t newSize = std::min(newStream.size(), std::max<size_t>(logstream.size(), 128 * 1024)); //do not cut in the middle of a row - auto iter = std::search(newStream.begin() + newSize, newStream.end(), std::begin(LINE_BREAK), std::end(LINE_BREAK) - 1); - if (iter != newStream.end()) + auto iter = std::search(newStream.cbegin() + newSize, newStream.cend(), std::begin(LINE_BREAK), std::end(LINE_BREAK) - 1); + if (iter != newStream.cend()) { - newStream.resize(iter - newStream.begin()); + newStream.resize(iter - newStream.cbegin()); newStream += LINE_BREAK; newStream += "[...]"; diff --git a/lib/icon_buffer.cpp b/lib/icon_buffer.cpp index 60f6cbe4..9274a0b4 100644 --- a/lib/icon_buffer.cpp +++ b/lib/icon_buffer.cpp @@ -537,7 +537,7 @@ IconBuffer::~IconBuffer() { setWorkload(std::vector<Zstring>()); //make sure interruption point is always reached! pimpl->worker.interrupt(); - pimpl->worker.join(); + pimpl->worker.join(); //we assume precondition "worker.joinable()"!!! } diff --git a/lib/lock_holder.h b/lib/lock_holder.h index d94b0fd6..6265747b 100644 --- a/lib/lock_holder.h +++ b/lib/lock_holder.h @@ -40,6 +40,8 @@ public: try { + //lock file creation is synchronous and may block noticably for very slow devices (usb sticks, mapped cloud storages) + procCallback.forceUiRefresh(); //=> make sure the right folder name is shown on GUI during this time! lockHolder.insert(std::make_pair(dirnameFmt, DirLock(dirnameFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback))); } catch (const FileError& e) diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp index e8b13003..b9d29699 100644 --- a/lib/parallel_scan.cpp +++ b/lib/parallel_scan.cpp @@ -539,7 +539,11 @@ void zen::fillBuffer(const std::set<DirectoryKey>& keysToRead, //in zen::ScopeGuard guardWorker = zen::makeGuard([&] { std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.interrupt(); }); //interrupt all at once, then join - std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.join(); }); + std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) + { + if (wt.joinable()) //this is a precondition of thread::join()!!! Latter will throw an exception if violated! + wt.join(); //in this context it is possible a thread is *not* joinable anymore due to the thread::timed_join() below! + }); }); std::shared_ptr<AsyncCallback> acb = std::make_shared<AsyncCallback>(); diff --git a/lib/process_xml.h b/lib/process_xml.h index ec1a142f..d21f7ffc 100644 --- a/lib/process_xml.h +++ b/lib/process_xml.h @@ -57,17 +57,19 @@ struct XmlGuiConfig bool showFilteredElements; OnGuiError handleError; //reaction on error situation during synchronization bool showSyncAction; - - bool operator==(const XmlGuiConfig& other) const - { - return mainCfg == other.mainCfg && - showFilteredElements == other.showFilteredElements && - handleError == other.handleError && - showSyncAction == other.showSyncAction; - } }; +inline +bool operator==(const XmlGuiConfig& lhs, const XmlGuiConfig& rhs) +{ + return lhs.mainCfg == rhs.mainCfg && + lhs.showFilteredElements == rhs.showFilteredElements && + lhs.handleError == rhs.handleError && + lhs.showSyncAction == rhs.showSyncAction; +} + + struct XmlBatchConfig { XmlBatchConfig() : diff --git a/lib/resolve_path.cpp b/lib/resolve_path.cpp index 11733136..0b8e80b9 100644 --- a/lib/resolve_path.cpp +++ b/lib/resolve_path.cpp @@ -20,6 +20,7 @@ #elif defined FFS_LINUX #include <zen/file_traverser.h> #include <unistd.h> +#include <stdlib.h> //getenv() #endif using namespace zen; @@ -46,11 +47,30 @@ Zstring resolveRelativePath(const Zstring& relativeName) //note: ::GetFullPathNa #elif defined FFS_LINUX Zstring resolveRelativePath(const Zstring& relativeName) { - //unfortunately ::realpath only resolves *existing* relative paths, so we have resolve to absolute by ourselves - //http://linux.die.net/man/2/path_resolution if (!startsWith(relativeName, FILE_NAME_SEPARATOR)) //absolute names are exactly those starting with a '/' { + /* + basic support for '~': strictly speaking this is a shell-layer feature, so "realpath()" won't handle it + http://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html + + http://linux.die.net/man/3/getpwuid: An application that wants to determine its user's home directory + should inspect the value of HOME (rather than the value getpwuid(getuid())->pw_dir) since this allows + the user to modify their notion of "the home directory" during a login session. + */ + if (startsWith(relativeName, "~/") || relativeName == "~") + { + const char* homeDir = ::getenv("HOME"); + if (!homeDir) + return relativeName; //error! no further processing! + + if (startsWith(relativeName, "~/")) + return appendSeparator(homeDir) + afterFirst(relativeName, '/'); + else if (relativeName == "~") + return homeDir; + } + + //unfortunately ::realpath only resolves *existing* relative paths, so we need to do it by ourselves std::vector<char> buffer(10000); if (::getcwd(&buffer[0], buffer.size()) != nullptr) return appendSeparator(&buffer[0]) + relativeName; @@ -426,9 +446,9 @@ Zstring expandVolumeName(const Zstring& text) // [volname]:\folder [volna } -#ifdef FFS_WIN void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, LessFilename>& output) { +#ifdef FFS_WIN //1. replace volume path by volume name: c:\dirname -> [SYSTEM]\dirname if (dirname.size() >= 3 && std::iswalpha(dirname[0]) && @@ -447,6 +467,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less if (output.insert(testVolname).second) getDirectoryAliasesRecursive(testVolname, output); //recurse! } +#endif //3. environment variables: C:\Users\username -> %USERPROFILE% { @@ -458,6 +479,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less if (std::unique_ptr<Zstring> value = getEnvironmentVar(envName)) envToDir.insert(std::make_pair(envName, *value)); }; +#ifdef FFS_WIN addEnvVar(L"AllUsersProfile"); // C:\ProgramData addEnvVar(L"AppData"); // C:\Users\username\AppData\Roaming addEnvVar(L"LocalAppData"); // C:\Users\username\AppData\Local @@ -475,16 +497,27 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less const auto& csidlMap = CsidlConstants::get(); envToDir.insert(csidlMap.begin(), csidlMap.end()); +#elif defined FFS_LINUX + addEnvVar("HOME"); // /home/zenju +#endif //substitute paths by symbolic names - Zstring tmp = dirname; - ::makeUpper(tmp); + auto pathStartsWith = [](const Zstring& path, const Zstring& prefix) -> bool + { +#ifdef FFS_WIN + Zstring tmp = path; + Zstring tmp2 = prefix; + ::makeUpper(tmp); + ::makeUpper(tmp2); + return startsWith(tmp, tmp2); +#elif defined FFS_LINUX + return startsWith(path, prefix); +#endif + }; std::for_each(envToDir.begin(), envToDir.end(), [&](const std::pair<Zstring, Zstring>& entry) { - Zstring tmp2 = entry.second; //case-insensitive "startsWith()" - ::makeUpper(tmp2); // - if (startsWith(tmp, tmp2)) - output.insert(MACRO_SEP + entry.first + MACRO_SEP + (dirname.c_str() + tmp2.size())); + if (pathStartsWith(dirname, entry.second)) + output.insert(MACRO_SEP + entry.first + MACRO_SEP + (dirname.c_str() + entry.second.size())); }); } @@ -513,7 +546,6 @@ std::vector<Zstring> zen::getDirectoryAliases(const Zstring& dirString) return std::vector<Zstring>(tmp.begin(), tmp.end()); } -#endif Zstring zen::getFormattedDirectoryName(const Zstring& dirString) // throw() diff --git a/lib/resolve_path.h b/lib/resolve_path.h index 0132b51f..975ed304 100644 --- a/lib/resolve_path.h +++ b/lib/resolve_path.h @@ -24,11 +24,11 @@ Zstring getFormattedDirectoryName(const Zstring& dirString); //throw() - non-blo //macro substitution only Zstring expandMacros(const Zstring& text); +std::vector<Zstring> getDirectoryAliases(const Zstring& dirString); + #ifdef FFS_WIN //*blocks* if network is not reachable or when showing login prompt dialog! void loginNetworkShare(const Zstring& dirname, bool allowUserInteraction); //throw() - user interaction: show OS password prompt - -std::vector<Zstring> getDirectoryAliases(const Zstring& dirString); #endif } diff --git a/lib/return_codes.h b/lib/return_codes.h index 0bd98a41..6742c975 100644 --- a/lib/return_codes.h +++ b/lib/return_codes.h @@ -12,6 +12,7 @@ namespace zen enum FfsReturnCode { FFS_RC_SUCCESS = 0, + FFS_RC_FINISHED_WITH_WARNINGS, FFS_RC_FINISHED_WITH_ERRORS, FFS_RC_ABORTED, FFS_RC_EXCEPTION, diff --git a/lib/status_handler.h b/lib/status_handler.h index 789293e4..93f9892c 100644 --- a/lib/status_handler.h +++ b/lib/status_handler.h @@ -75,8 +75,8 @@ protected: if (updateUiIsAllowed()) //test if specific time span between ui updates is over forceUiRefresh(); - if (abortRequested) - abortThisProcess(); //abort can be triggered by requestAbortion() + if (abortRequested) //check *after* GUI update, to have up-to-date screen + abortThisProcess(); //triggered by requestAbortion() } virtual void reportStatus(const std::wstring& text) { statusText_ = text; requestUiRefresh(); /*throw AbortThisProcess */ } |