summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:21:59 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:21:59 +0200
commitd4af25c52a28b93484ffb55e0a8027bc4ce7856f (patch)
tree853d57468d6b370711e7a5dd2c3dc7d5bac81b10 /lib
parent5.8 (diff)
downloadFreeFileSync-d4af25c52a28b93484ffb55e0a8027bc4ce7856f.tar.gz
FreeFileSync-d4af25c52a28b93484ffb55e0a8027bc4ce7856f.tar.bz2
FreeFileSync-d4af25c52a28b93484ffb55e0a8027bc4ce7856f.zip
5.9
Diffstat (limited to 'lib')
-rw-r--r--lib/db_file.cpp4
-rw-r--r--lib/dir_lock.cpp2
-rw-r--r--lib/generate_logfile.h14
-rw-r--r--lib/icon_buffer.cpp2
-rw-r--r--lib/lock_holder.h2
-rw-r--r--lib/parallel_scan.cpp6
-rw-r--r--lib/process_xml.h18
-rw-r--r--lib/resolve_path.cpp52
-rw-r--r--lib/resolve_path.h4
-rw-r--r--lib/return_codes.h1
-rw-r--r--lib/status_handler.h4
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 */ }
bgstack15