From 90bc692185a27f18acb6b029dfaf038e555ef8ff Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Fri, 19 May 2023 09:24:58 -0400 Subject: add upstream 12.3 --- zen/dir_watcher.cpp | 10 +++--- zen/file_access.cpp | 2 +- zen/file_traverser.cpp | 82 +++++++++++++++++++++++++------------------------- zen/file_traverser.h | 4 +-- zen/string_tools.h | 8 ++--- zen/time.h | 4 +-- 6 files changed, 55 insertions(+), 55 deletions(-) (limited to 'zen') diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp index 235c466c..dccc149d 100644 --- a/zen/dir_watcher.cpp +++ b/zen/dir_watcher.cpp @@ -40,11 +40,11 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError traverse = [&traverse, &fullFolderList](const Zstring& path) //throw FileError { traverseFolder(path, nullptr, - [&](const FolderInfo& fi ) - { - fullFolderList.push_back(fi.fullPath); - traverse(fi.fullPath); //throw FileError - }, + [&](const FolderInfo& fi ) + { + fullFolderList.push_back(fi.fullPath); + traverse(fi.fullPath); //throw FileError + }, nullptr /*don't traverse into symlinks (analog to Windows)*/); //throw FileError }; diff --git a/zen/file_access.cpp b/zen/file_access.cpp index c5cbf095..24e418c9 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -88,7 +88,7 @@ std::variant getItemTypeIfExist //- case-sensitive comparison! itemPath must be normalized! //- finding the item after getItemType() previously failed is exceptional } - catch (const FileError& e) { throw SysError(replaceCpy(e.toString(), L"\n\n", L'\n')); } + catch (const FileError& e2) { throw SysError(replaceCpy(e2.toString(), L"\n\n", L'\n')); } return *parentPath; } diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index 4b33d3e6..4c3e2f97 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -19,60 +19,60 @@ void zen::traverseFolder(const Zstring& dirPath, const std::function& onFolder, const std::function& onSymlink) //throw FileError { - DIR* folder = ::opendir(dirPath.c_str()); //directory must NOT end with path separator, except "/" - if (!folder) - THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot open directory %x."), L"%x", fmtPath(dirPath)), "opendir"); - ZEN_ON_SCOPE_EXIT(::closedir(folder)); //never close nullptr handles! -> crash + DIR* folder = ::opendir(dirPath.c_str()); //directory must NOT end with path separator, except "/" + if (!folder) + THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot open directory %x."), L"%x", fmtPath(dirPath)), "opendir"); + ZEN_ON_SCOPE_EXIT(::closedir(folder)); //never close nullptr handles! -> crash - for (;;) + for (;;) + { + errno = 0; + const dirent* dirEntry = ::readdir(folder); //don't use readdir_r(), see comment in native.cpp + if (!dirEntry) { - errno = 0; - const dirent* dirEntry = ::readdir(folder); //don't use readdir_r(), see comment in native.cpp - if (!dirEntry) - { - if (errno == 0) //errno left unchanged => no more items - return; + if (errno == 0) //errno left unchanged => no more items + return; - THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), "readdir"); - //don't retry but restart dir traversal on error! https://devblogs.microsoft.com/oldnewthing/20140612-00/?p=753/ - } + THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), "readdir"); + //don't retry but restart dir traversal on error! https://devblogs.microsoft.com/oldnewthing/20140612-00/?p=753/ + } - //don't return "." and ".." - const char* itemNameRaw = dirEntry->d_name; + //don't return "." and ".." + const char* itemNameRaw = dirEntry->d_name; - if (itemNameRaw[0] == '.' && - (itemNameRaw[1] == 0 || (itemNameRaw[1] == '.' && itemNameRaw[2] == 0))) - continue; + if (itemNameRaw[0] == '.' && + (itemNameRaw[1] == 0 || (itemNameRaw[1] == '.' && itemNameRaw[2] == 0))) + continue; - const Zstring& itemName = itemNameRaw; - if (itemName.empty()) //checks result of normalizeUtfForPosix, too! - throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), formatSystemError("readdir", L"", L"Folder contains an item without name.")); + const Zstring& itemName = itemNameRaw; + if (itemName.empty()) //checks result of normalizeUtfForPosix, too! + throw FileError(replaceCpy(_("Cannot read directory %x."), L"%x", fmtPath(dirPath)), formatSystemError("readdir", L"", L"Folder contains an item without name.")); - const Zstring& itemPath = appendPath(dirPath, itemName); + const Zstring& itemPath = appendPath(dirPath, itemName); - struct stat statData = {}; - if (::lstat(itemPath.c_str(), &statData) != 0) //lstat() does not resolve symlinks - THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); + struct stat statData = {}; + if (::lstat(itemPath.c_str(), &statData) != 0) //lstat() does not resolve symlinks + THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); - if (S_ISLNK(statData.st_mode)) //on Linux there is no distinction between file and directory symlinks! - { - if (onSymlink) - onSymlink({ itemName, itemPath, statData.st_mtime}); - } - else if (S_ISDIR(statData.st_mode)) //a directory - { - if (onFolder) - onFolder({itemName, itemPath}); - } - else //a file or named pipe, etc. S_ISREG, S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK - { - if (onFile) - onFile({itemName, itemPath, makeUnsigned(statData.st_size), statData.st_mtime}); + if (S_ISLNK(statData.st_mode)) //on Linux there is no distinction between file and directory symlinks! + { + if (onSymlink) + onSymlink({ itemName, itemPath, statData.st_mtime}); + } + else if (S_ISDIR(statData.st_mode)) //a directory + { + if (onFolder) + onFolder({itemName, itemPath}); + } + else //a file or named pipe, etc. S_ISREG, S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK + { + if (onFile) + onFile({itemName, itemPath, makeUnsigned(statData.st_size), statData.st_mtime}); /* It may be a good idea to not check "S_ISREG(statData.st_mode)" explicitly and to not issue an error message on other types to support these scenarios: - RTS setup watch (essentially wants to read directories only) - removeDirectory (wants to delete everything; pipes can be deleted just like files via "unlink") However an "open" on a pipe will block (https://sourceforge.net/p/freefilesync/bugs/221/), so the copy routines better be smart! */ - } } + } } diff --git a/zen/file_traverser.h b/zen/file_traverser.h index 8903548d..c57b7d36 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -36,8 +36,8 @@ struct SymlinkInfo //- non-recursive void traverseFolder(const Zstring& dirPath, - const std::function& onFile, /*optional*/ - const std::function& onFolder,/*optional*/ + const std::function& onFile, /*optional*/ + const std::function& onFolder,/*optional*/ const std::function& onSymlink/*optional*/); //throw FileError } diff --git a/zen/string_tools.h b/zen/string_tools.h index 1cd8ef0d..3aa1c1d6 100644 --- a/zen/string_tools.h +++ b/zen/string_tools.h @@ -639,17 +639,17 @@ int saferPrintf(wchar_t* buffer, size_t bufferSize, const wchar_t* format, const template inline S printNumber(const T& format, const Num& number) //format a single number using ::sprintf { -#ifdef __cpp_lib_format -#error refactor? -#endif static_assert(std::is_same_v, GetCharTypeT>); assert(strBegin(format)[strLength(format)] == 0); //format must be null-terminated! S buf(128, static_cast>('0')); const int charsWritten = impl::saferPrintf(buf.data(), buf.size(), strBegin(format), number); - if (makeUnsigned(charsWritten) > buf.size()) + if (charsWritten < 0 || makeUnsigned(charsWritten) > buf.size()) + { + assert(false); return S(); + } buf.resize(charsWritten); return buf; diff --git a/zen/time.h b/zen/time.h index ee43566b..aa7df21b 100644 --- a/zen/time.h +++ b/zen/time.h @@ -391,7 +391,7 @@ TimeComp parseTime(const String& format, const String2& str) inline Zstring formatTimeSpan(int64_t timeInSec, bool hourOptional) { - Zstring timespanStr; + Zstring timespanStr; if (timeInSec < 0) { @@ -409,7 +409,7 @@ Zstring formatTimeSpan(int64_t timeInSec, bool hourOptional) timeInSec -= days * secsPerDay; timespanStr += numberTo(days) + Zstr("."); //don't need zen::formatNumber(), do we? } - + //format time span as if absolute UTC time const TimeComp& tc = getUtcTime(timeInSec); //returns TimeComp() on error timespanStr += formatTime(timeSpanFmt, tc); //returns empty string on error -- cgit