summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorB. Stack <bgstack15@gmail.com>2023-06-20 07:46:53 -0400
committerB. Stack <bgstack15@gmail.com>2023-06-20 07:46:53 -0400
commitf76994f1fb3e25c4563c9d8afce6bbc86701d1d2 (patch)
treeb39389163603195a0169af57712eb0765e5c11f4 /zen
parentadd upstream 12.3 (diff)
downloadFreeFileSync-12.4.tar.gz
FreeFileSync-12.4.tar.bz2
FreeFileSync-12.4.zip
add upstream 12.412.4
Diffstat (limited to 'zen')
-rw-r--r--zen/file_access.cpp12
-rw-r--r--zen/file_io.cpp6
-rw-r--r--zen/file_path.cpp1
-rw-r--r--zen/json.h2
-rw-r--r--zen/legacy_compiler.h6
-rw-r--r--zen/perf.h30
-rw-r--r--zen/scope_guard.h2
-rw-r--r--zen/serialize.h16
-rw-r--r--zen/symlink_target.h14
-rw-r--r--zen/sys_info.cpp12
-rw-r--r--zen/sys_info.h4
-rw-r--r--zen/utf.h2
12 files changed, 65 insertions, 42 deletions
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 24e418c9..6c47936c 100644
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -64,7 +64,7 @@ std::variant<ItemType, Zstring /*last existing parent path*/> getItemTypeIfExist
}
catch (const SysErrorCode& e) //let's dig deeper, but *only* if error code sounds like "not existing"
{
- const std::optional<Zstring> parentPath = getParentFolderPath(itemPath);
+ const std::optional<Zstring>& parentPath = getParentFolderPath(itemPath);
if (!parentPath) //device root => quick access test
throw;
if (e.errorCode == ENOENT)
@@ -178,8 +178,6 @@ uint64_t zen::getFileSize(const Zstring& filePath) //throw FileError
}
-
-
Zstring zen::getTempFolderPath() //throw FileError
{
if (const std::optional<Zstring> tempDirPath = getEnvironmentVar("TMPDIR"))
@@ -561,7 +559,7 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File
}
catch (FileError&) //not yet existing or access error
{
- const std::optional<Zstring> parentPath = getParentFolderPath(dirPathEx);
+ const std::optional<Zstring>& parentPath = getParentFolderPath(dirPathEx);
if (!parentPath)//device root => quick access test
throw;
dirNames.push_front(getItemName(dirPathEx));
@@ -667,7 +665,7 @@ FileCopyResult zen::copyNewFile(const Zstring& sourceFile, const Zstring& target
}
FileOutputPlain fileOut(fdTarget, targetFile); //pass ownership
- //preallocate disk space + reduce fragmentation (perf: no real benefit)
+ //preallocate disk space + reduce fragmentation
fileOut.reserveSpace(sourceInfo.st_size); //throw FileError
unbufferedStreamCopy([&](void* buffer, size_t bytesToRead)
@@ -686,8 +684,10 @@ FileCopyResult zen::copyNewFile(const Zstring& sourceFile, const Zstring& target
},
fileOut.getBlockSize() /*throw FileError*/); //throw FileError, X
+ //possible improvement: copy_file_range() performs an in-kernel copy: https://github.com/coreutils/coreutils/blob/17479ef60c8edbd2fe8664e31a7f69704f0cd221/src/copy.c#L342
+
#if 0
- //clean file system cache: needed at all? no user complaints at all!!!
+ //clean file system cache: needed at all? no user complaints at all so far!!!
//posix_fadvise(POSIX_FADV_DONTNEED) does nothing, unless data was already read from/written to disk: https://insights.oetiker.ch/linux/fadvise/
// => should be "most" of the data at this point => good enough?
if (::posix_fadvise(fileIn.getHandle(), 0 /*offset*/, 0 /*len*/, POSIX_FADV_DONTNEED) != 0) //"len == 0" means "end of the file"
diff --git a/zen/file_io.cpp b/zen/file_io.cpp
index 2e4ab60a..8c985f64 100644
--- a/zen/file_io.cpp
+++ b/zen/file_io.cpp
@@ -245,6 +245,11 @@ void FileOutputPlain::reserveSpace(uint64_t expectedSize) //throw FileError
try
{
+#if 0 /* fallocate(FALLOC_FL_KEEP_SIZE):
+ - perf: no real benefit (in a quick and dirty local test)
+ - breaks Btrfs compression: https://freefilesync.org/forum/viewtopic.php?t=10356
+ - apparently not even used by cp: https://github.com/coreutils/coreutils/blob/17479ef60c8edbd2fe8664e31a7f69704f0cd221/src/copy.c#LL1234C5-L1234C5 */
+
//don't use ::posix_fallocate which uses horribly inefficient fallback if FS doesn't support it (EOPNOTSUPP) and changes files size!
//FALLOC_FL_KEEP_SIZE => allocate only, file size is NOT changed!
if (::fallocate(getHandle(), //int fd
@@ -253,6 +258,7 @@ void FileOutputPlain::reserveSpace(uint64_t expectedSize) //throw FileError
expectedSize) != 0) //off_t len
if (errno != EOPNOTSUPP) //possible, unlike with posix_fallocate()
THROW_LAST_SYS_ERROR("fallocate");
+#endif
}
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), e.toString()); }
diff --git a/zen/file_path.cpp b/zen/file_path.cpp
index c9d6f236..60ac4eb7 100644
--- a/zen/file_path.cpp
+++ b/zen/file_path.cpp
@@ -5,6 +5,7 @@
// *****************************************************************************
#include "file_path.h"
+#include "thread.h"
using namespace zen;
diff --git a/zen/json.h b/zen/json.h
index be2cfbab..8959e995 100644
--- a/zen/json.h
+++ b/zen/json.h
@@ -333,7 +333,7 @@ public:
Scanner(const std::string& stream) : stream_(stream), pos_(stream_.begin())
{
if (zen::startsWith(stream_, BYTE_ORDER_MARK_UTF8))
- pos_ += strLength(BYTE_ORDER_MARK_UTF8);
+ pos_ += BYTE_ORDER_MARK_UTF8.size();
}
Token getNextToken() //throw JsonParsingError
diff --git a/zen/legacy_compiler.h b/zen/legacy_compiler.h
index 8606f95c..2070d60f 100644
--- a/zen/legacy_compiler.h
+++ b/zen/legacy_compiler.h
@@ -20,7 +20,8 @@
GCC https://gcc.gnu.org/projects/cxx-status.html
libstdc++ https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
- Clang https://clang.llvm.org/cxx_status.html#cxx20
+ Clang https://clang.llvm.org/cxx_status.html
+ Xcode https://developer.apple.com/xcode/cpp
libc++ https://libcxx.llvm.org/cxx2a_status.html */
@@ -39,6 +40,9 @@ basic_string<Char, Traits, Alloc> operator+(basic_string<Char, Traits, Alloc>&&
}
//---------------------------------------------------------------------------------
+//support for std::string::resize_and_overwrite()
+#define ZEN_HAVE_RESIZE_AND_OVERWRITE 1
+
namespace zen
{
double fromChars(const char* first, const char* last);
diff --git a/zen/perf.h b/zen/perf.h
index c3315717..a0cc905a 100644
--- a/zen/perf.h
+++ b/zen/perf.h
@@ -40,45 +40,35 @@ namespace zen
class StopWatch
{
public:
- explicit StopWatch(bool startPaused = false) : paused_(startPaused) {}
+ explicit StopWatch(bool startPaused = false)
+ {
+ if (startPaused)
+ startTime_ = {};
+ }
- bool isPaused() const { return paused_; }
+ bool isPaused() const { return startTime_ == std::chrono::steady_clock::time_point{}; }
void pause()
{
- if (!paused_)
- {
- paused_ = true;
- elapsedUntilPause_ += std::chrono::steady_clock::now() - startTime_;
- }
+ if (!isPaused())
+ elapsedUntilPause_ += std::chrono::steady_clock::now() - std::exchange(startTime_, {});
}
void resume()
{
- if (paused_)
- {
- paused_ = false;
+ if (isPaused())
startTime_ = std::chrono::steady_clock::now();
- }
- }
-
- void restart()
- {
- paused_ = false;
- startTime_ = std::chrono::steady_clock::now();
- elapsedUntilPause_ = std::chrono::nanoseconds::zero();
}
std::chrono::nanoseconds elapsed() const
{
auto elapsedTotal = elapsedUntilPause_;
- if (!paused_)
+ if (!isPaused())
elapsedTotal += std::chrono::steady_clock::now() - startTime_;
return elapsedTotal;
}
private:
- bool paused_;
std::chrono::steady_clock::time_point startTime_ = std::chrono::steady_clock::now();
std::chrono::nanoseconds elapsedUntilPause_{}; //std::chrono::duration is uninitialized by default! WTF! When will this stupidity end!
};
diff --git a/zen/scope_guard.h b/zen/scope_guard.h
index 4cc049a8..9b27eecb 100644
--- a/zen/scope_guard.h
+++ b/zen/scope_guard.h
@@ -23,7 +23,7 @@ namespace zen
Scope Exit:
ZEN_ON_SCOPE_EXIT (CleanUp());
- ZEN_ON_SCOPE_FAIL (UndoPreviousWork());
+ ZEN_ON_SCOPE_FAIL (UndoTemporaryWork());
ZEN_ON_SCOPE_SUCCESS(NotifySuccess()); */
enum class ScopeGuardRunMode
diff --git a/zen/serialize.h b/zen/serialize.h
index 8ccecd53..02dcd2b2 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -261,11 +261,21 @@ BinContainer unbufferedLoad(Function tryRead /*(void* buffer, size_t bytesToRead
BinContainer buf;
for (;;)
{
- warn_static("don't need zero-initialization!")
- buf.resize(buf.size() + blockSize);
+#ifndef ZEN_HAVE_RESIZE_AND_OVERWRITE
+#error include legacy_compiler.h!
+#endif
+#if ZEN_HAVE_RESIZE_AND_OVERWRITE //permature(?) perf optimization; avoid needless zero-initialization:
+ size_t bytesRead = 0;
+ buf.resize_and_overwrite(buf.size() + blockSize, [&, bufSizeOld = buf.size()](char* rawBuf, size_t /*rawBufSize: caveat: may be larger than what's requested*/)
+ {
+ bytesRead = tryRead(rawBuf + bufSizeOld, blockSize); //throw X; may return short; only 0 means EOF
+ return bufSizeOld + bytesRead;
+ });
+#else
+ buf.resize(buf.size() + blockSize); //needless zero-initialization!
const size_t bytesRead = tryRead(buf.data() + buf.size() - blockSize, blockSize); //throw X; may return short; only 0 means EOF
buf.resize(buf.size() - blockSize + bytesRead); //caveat: unsigned arithmetics
-
+#endif
if (bytesRead == 0) //end of file
{
//caveat: memory consumption of returned string!
diff --git a/zen/symlink_target.h b/zen/symlink_target.h
index 083360af..8580a9dd 100644
--- a/zen/symlink_target.h
+++ b/zen/symlink_target.h
@@ -8,6 +8,7 @@
#define SYMLINK_TARGET_H_801783470198357483
#include "file_error.h"
+#include "file_path.h"
#include <unistd.h>
#include <stdlib.h> //realpath
@@ -35,12 +36,14 @@ Zstring getSymlinkResolvedPath(const Zstring& linkPath); //throw FileError
//################################ implementation ################################
+
+namespace zen
+{
namespace
{
//retrieve raw target data of symlink or junction
-zen::SymlinkRawContent getSymlinkRawContent_impl(const Zstring& linkPath) //throw SysError
+SymlinkRawContent getSymlinkRawContent_impl(const Zstring& linkPath) //throw SysError
{
- using namespace zen;
const size_t bufSize = 10000;
std::vector<char> buf(bufSize);
@@ -54,9 +57,8 @@ zen::SymlinkRawContent getSymlinkRawContent_impl(const Zstring& linkPath) //thro
}
-Zstring getResolvedSymlinkPath_impl(const Zstring& linkPath) //throw SysError
+Zstring getSymlinkResolvedPath_impl(const Zstring& linkPath) //throw SysError
{
- using namespace zen;
char* targetPath = ::realpath(linkPath.c_str(), nullptr);
if (!targetPath)
THROW_LAST_SYS_ERROR("realpath");
@@ -66,8 +68,6 @@ Zstring getResolvedSymlinkPath_impl(const Zstring& linkPath) //throw SysError
}
-namespace zen
-{
inline
SymlinkRawContent getSymlinkRawContent(const Zstring& linkPath)
{
@@ -84,7 +84,7 @@ Zstring getSymlinkResolvedPath(const Zstring& linkPath)
{
try
{
- return getResolvedSymlinkPath_impl(linkPath); //throw SysError
+ return getSymlinkResolvedPath_impl(linkPath); //throw SysError
}
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot determine final path for %x."), L"%x", fmtPath(linkPath)), e.toString()); }
}
diff --git a/zen/sys_info.cpp b/zen/sys_info.cpp
index 2a32d247..c3680ec7 100644
--- a/zen/sys_info.cpp
+++ b/zen/sys_info.cpp
@@ -207,7 +207,7 @@ std::wstring zen::getOsDescription() //throw FileError
-Zstring zen::getRealProcessPath() //throw FileError
+Zstring zen::getProcessPath() //throw FileError
{
try
{
@@ -284,3 +284,13 @@ Zstring zen::getUserDownloadsPath() //throw FileError
}
catch (const SysError& e) { throw FileError(_("Cannot get process information."), e.toString()); }
}
+
+
+bool zen::runningElevated() //throw FileError
+{
+ if (::geteuid() != 0) //nofail; non-root
+ return false;
+
+ return getLoginUser() != "root"; //throw FileError
+ //consider "root login" like "UAC disabled" on Windows
+}
diff --git a/zen/sys_info.h b/zen/sys_info.h
index ce07d7a1..ed5dc1d6 100644
--- a/zen/sys_info.h
+++ b/zen/sys_info.h
@@ -30,12 +30,14 @@ ComputerModel getComputerModel(); //throw FileError
std::wstring getOsDescription(); //throw FileError
-Zstring getRealProcessPath(); //throw FileError
+Zstring getProcessPath(); //throw FileError
Zstring getUserDownloadsPath(); //throw FileError
Zstring getUserDataPath(); //throw FileError
Zstring getUserHome(); //throw FileError
+
+bool runningElevated(); //throw FileError
}
#endif //SYSTEM_H_4189731847832147508915
diff --git a/zen/utf.h b/zen/utf.h
index 6f7c39cc..aad05aba 100644
--- a/zen/utf.h
+++ b/zen/utf.h
@@ -16,7 +16,7 @@ namespace zen
template <class TargetString, class SourceString>
TargetString utfTo(const SourceString& str);
-const std::string_view BYTE_ORDER_MARK_UTF8 = "\xEF\xBB\xBF";
+constexpr std::string_view BYTE_ORDER_MARK_UTF8 = "\xEF\xBB\xBF";
template <class UtfString>
bool isValidUtf(const UtfString& str); //check for UTF-8 encoding errors
bgstack15