diff options
Diffstat (limited to 'zen')
-rw-r--r-- | zen/dst_hack.cpp | 2 | ||||
-rw-r--r-- | zen/file_handling.cpp | 23 | ||||
-rw-r--r-- | zen/notify_removal.cpp | 39 | ||||
-rw-r--r-- | zen/perf.h | 18 | ||||
-rw-r--r-- | zen/process_priority.cpp | 55 | ||||
-rw-r--r-- | zen/process_priority.h | 8 | ||||
-rw-r--r-- | zen/recycler.cpp | 13 | ||||
-rw-r--r-- | zen/tick_count.h | 6 | ||||
-rw-r--r-- | zen/type_traits.h | 6 | ||||
-rw-r--r-- | zen/zstring.cpp | 7 |
10 files changed, 59 insertions, 118 deletions
diff --git a/zen/dst_hack.cpp b/zen/dst_hack.cpp index 52d45679..b38f73b4 100644 --- a/zen/dst_hack.cpp +++ b/zen/dst_hack.cpp @@ -57,7 +57,7 @@ bool dst::isFatDrive(const Zstring& filepath) //throw() return false; const DWORD bufferSize = MAX_PATH + 1; - wchar_t fsName[bufferSize]; + wchar_t fsName[bufferSize] = {}; //suprisingly fast: ca. 0.03 ms per call! if (!::GetVolumeInformation(appendSeparator(volumePath).c_str(), //__in_opt LPCTSTR lpRootPathName, diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp index b4622a9c..75062462 100644 --- a/zen/file_handling.cpp +++ b/zen/file_handling.cpp @@ -20,7 +20,6 @@ #include <Aclapi.h> #include "privilege.h" #include "dll.h" -#include "win.h" //includes "windows.h" #include "long_path_prefix.h" #include "dst_hack.h" #include "win_ver.h" @@ -828,8 +827,8 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const nullptr, &lastWriteTimeDbg)); - assert(std::abs(filetimeToTimeT(creationTimeDbg ) - filetimeToTimeT(creationTime )) <= 2); //respect 2 second FAT/FAT32 precision - assert(std::abs(filetimeToTimeT(lastWriteTimeDbg) - filetimeToTimeT(lastWriteTime)) <= 2); // + assert(std::abs(filetimeToTimeT(lastWriteTimeDbg) - filetimeToTimeT(lastWriteTime)) <= 2); //respect 2 second FAT/FAT32 precision + //assert(std::abs(filetimeToTimeT(creationTimeDbg ) - filetimeToTimeT(creationTime )) <= 2); -> creation time not available for Linux-hosted Samba shares! #endif } #endif @@ -1632,7 +1631,7 @@ void copyFileWindowsSparse(const Zstring& sourceFile, throw FileError(errorMsg, errorDescr); } - ScopeGuard guardTarget = makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {} }); //transactional behavior: guard just after opening target and before managing hFileOut + ScopeGuard guardTarget = makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {} }); //transactional behavior: guard just after opening target and before managing hFileTarget ZEN_ON_SCOPE_EXIT(::CloseHandle(hFileTarget)); //---------------------------------------------------------------------- @@ -1772,26 +1771,26 @@ void copyFileWindowsSparse(const Zstring& sourceFile, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); if (hFileTarget == INVALID_HANDLE_VALUE) - throw 1; + throw FileError(L"fail"); ZEN_ON_SCOPE_EXIT(::CloseHandle(hSparse)); DWORD br = 0; if (!::DeviceIoControl(hSparse, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &br,nullptr)) - throw 1; + throw FileError(L"fail"); LARGE_INTEGER liDistanceToMove = {}; liDistanceToMove.QuadPart = 1024 * 1024 * 1024; //create 5 TB sparse file liDistanceToMove.QuadPart *= 5 * 1024; //maximum file size on NTFS: 16 TB - 64 kB if (!::SetFilePointerEx(hSparse, liDistanceToMove, nullptr, FILE_BEGIN)) - throw 1; + throw FileError(L"fail"); if (!SetEndOfFile(hSparse)) - throw 1; + throw FileError(L"fail"); FILE_ZERO_DATA_INFORMATION zeroInfo = {}; zeroInfo.BeyondFinalZero.QuadPart = liDistanceToMove.QuadPart; if (!::DeviceIoControl(hSparse, FSCTL_SET_ZERO_DATA, &zeroInfo, sizeof(zeroInfo), nullptr, 0, &br, nullptr)) - throw 1; + throw FileError(L"fail"); */ } @@ -2044,6 +2043,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile, dst::isFatDrive(targetFile) && getFilesize(sourceFile) >= 4U * std::uint64_t(1024U * 1024 * 1024)) //throw FileError errorDescr += L"\nFAT volumes cannot store files larger than 4 gigabyte."; + //see "Limitations of the FAT32 File System": http://support.microsoft.com/kb/314463/en-us //note: ERROR_INVALID_PARAMETER can also occur when copying to a SharePoint server or MS SkyDrive and the target filepath is of a restricted type. } @@ -2255,14 +2255,15 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath Zstring tmpTarget = targetFile + TEMP_FILE_ENDING; //use temporary file until a correct date has been set //raw file copy - for (int i = 1;; ++i) + for (int i = 0;; ++i) try { copyFileSelectOs(sourceFile, tmpTarget, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked break; } - catch (const ErrorTargetExisting&) //using optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses + catch (const ErrorTargetExisting&) //optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses { + if (i == 10) throw; //avoid endless recursion in pathological cases, e.g. https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/36adac33 tmpTarget = targetFile + Zchar('_') + numberTo<Zstring>(i) + TEMP_FILE_ENDING; } diff --git a/zen/notify_removal.cpp b/zen/notify_removal.cpp index 3de375f2..45a39c48 100644 --- a/zen/notify_removal.cpp +++ b/zen/notify_removal.cpp @@ -38,7 +38,7 @@ private: MessageProvider (const MessageProvider&) = delete; MessageProvider& operator=(const MessageProvider&) = delete; - static const wchar_t dummyWindowName[]; + static const wchar_t dummyClassName[]; static LRESULT CALLBACK topWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -51,7 +51,7 @@ private: }; -const wchar_t MessageProvider::dummyWindowName[] = L"E6AD5EB1-527B-4EEF-AC75-27883B233380"; //random name +const wchar_t MessageProvider::dummyClassName[] = L"E6AD5EB1-527B-4EEF-AC75-27883B233380"; //random name LRESULT CALLBACK MessageProvider::topWndProc(HWND hwnd, //handle to window @@ -81,37 +81,30 @@ MessageProvider::MessageProvider() : WNDCLASS wc = {}; wc.lpfnWndProc = topWndProc; wc.hInstance = hMainModule; - wc.lpszClassName = dummyWindowName; + wc.lpszClassName = dummyClassName; if (::RegisterClass(&wc) == 0) throwFileError(_("Unable to register to receive system messages."), L"RegisterClass", getLastError()); - ScopeGuard guardClass = makeGuard([&] { ::UnregisterClass(dummyWindowName, hMainModule); }); + ScopeGuard guardClass = makeGuard([&] { ::UnregisterClass(dummyClassName, hMainModule); }); //create dummy-window - windowHandle = ::CreateWindow(dummyWindowName, //LPCTSTR lpClassName OR ATOM in low-order word! - nullptr, //LPCTSTR lpWindowName, - 0, //DWORD dwStyle, - 0, //int x, - 0, //int y, - 0, //int nWidth, - 0, //int nHeight, - 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)! - nullptr, //HMENU hMenu, - hMainModule, //HINSTANCE hInstance, - nullptr); //LPVOID lpParam + windowHandle = ::CreateWindow(dummyClassName, //_In_opt_ LPCTSTR lpClassName, + nullptr, //_In_opt_ LPCTSTR lpWindowName, + 0, //_In_ DWORD dwStyle, + 0, 0, 0, 0, //_In_ int x, y, nWidth, nHeight, + nullptr, //_In_opt_ HWND hWndParent; we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)! + nullptr, //_In_opt_ HMENU hMenu, + hMainModule, //_In_opt_ HINSTANCE hInstance, + nullptr); //_In_opt_ LPVOID lpParam if (!windowHandle) throwFileError(_("Unable to register to receive system messages."), L"CreateWindow", getLastError()); //store this-pointer for topWndProc() to use: do this AFTER CreateWindow() to avoid processing messages while this constructor is running!!! //unlike: http://blogs.msdn.com/b/oldnewthing/archive/2014/02/03/10496248.aspx ::SetLastError(ERROR_SUCCESS); //[!] required for proper error handling, see MSDN, SetWindowLongPtr - if (::SetWindowLongPtr(windowHandle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)) == 0) - { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - if (lastError != ERROR_SUCCESS) - throwFileError(_("Unable to register to receive system messages."), L"SetWindowLongPtr", lastError); - } + if (::SetWindowLongPtr(windowHandle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)) == 0 && ::GetLastError() != ERROR_SUCCESS) + throwFileError(_("Unable to register to receive system messages."), L"SetWindowLongPtr", ::GetLastError()); guardClass.dismiss(); } @@ -121,8 +114,8 @@ MessageProvider::~MessageProvider() { //clean-up in reverse order ::DestroyWindow(windowHandle); - ::UnregisterClass(dummyWindowName, //LPCTSTR lpClassName OR ATOM in low-order word! - hMainModule); //HINSTANCE hInstance + ::UnregisterClass(dummyClassName, //LPCTSTR lpClassName OR ATOM in low-order word! + hMainModule); //HINSTANCE hInstance } @@ -4,8 +4,8 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef DEBUG_PERF_HEADER -#define DEBUG_PERF_HEADER +#ifndef DEBUG_PERF_HEADER_83947184145342652456 +#define DEBUG_PERF_HEADER_83947184145342652456 #include "deprecate.h" #include "tick_count.h" @@ -30,14 +30,10 @@ public: ZEN_DEPRECATE PerfTimer() : //throw TimerError - ticksPerSec_(ticksPerSec()), startTime(), resultShown(false) + ticksPerSec_(ticksPerSec()), startTime(getTicks()), resultShown(false) { - //std::clock() - "counts CPU time in C and wall time in VC++" - WTF!??? -#ifdef ZEN_WIN - if (::SetThreadAffinityMask(::GetCurrentThread(), 1) == 0) //"should not be required unless there are bugs in BIOS or HAL" - msdn, QueryPerformanceCounter - throw TimerError(); -#endif - startTime = getTicks(); + //std::clock() - "counts CPU time in Linux GCC and wall time in VC++" - WTF!??? + if (ticksPerSec_ == 0 || !startTime.isValid()) throw TimerError(); } @@ -50,7 +46,7 @@ public: if (!now.isValid()) throw TimerError(); - const auto delta = static_cast<long>(1000.0 * dist(startTime, now) / ticksPerSec_); + const std::int64_t delta = 1000 * dist(startTime, now) / ticksPerSec_; #ifdef ZEN_WIN std::ostringstream ss; ss << delta << " ms"; @@ -72,4 +68,4 @@ private: }; } -#endif //DEBUG_PERF_HEADER +#endif //DEBUG_PERF_HEADER_83947184145342652456 diff --git a/zen/process_priority.cpp b/zen/process_priority.cpp index d2f6dc26..ee8e7d8b 100644 --- a/zen/process_priority.cpp +++ b/zen/process_priority.cpp @@ -5,17 +5,11 @@ // ************************************************************************** #include "process_priority.h" -#include "sys_error.h" +//#include "sys_error.h" #include "i18n.h" #ifdef ZEN_WIN #include "win.h" //includes "windows.h" - -#elif defined ZEN_LINUX - -#elif defined ZEN_MAC -#include <sys/resource.h> //getiopolicy_np -#include <IOKit/pwr_mgt/IOPMLib.h> //keep in .cpp file to not pollute global namespace! #endif using namespace zen; @@ -99,51 +93,4 @@ private: const int oldIoPrio; }; */ - -#elif defined ZEN_MAC -//https://developer.apple.com/library/mac/#qa/qa1340 -struct PreventStandby::Pimpl -{ - Pimpl() : assertionID() {} - IOPMAssertionID assertionID; -}; - -PreventStandby::PreventStandby() : pimpl(make_unique<Pimpl>()) -{ - IOReturn rv = ::IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, - kIOPMAssertionLevelOn, - CFSTR("FreeFileSync"), - &pimpl->assertionID); - if (rv != kIOReturnSuccess) - throw FileError(_("Unable to suspend system sleep mode."), replaceCpy<std::wstring>(L"IOReturn Code %x", L"%x", numberTo<std::wstring>(rv))); //could not find a better way to convert IOReturn to string -} - -PreventStandby::~PreventStandby() -{ - ::IOPMAssertionRelease(pimpl->assertionID); -} - - -struct ScheduleForBackgroundProcessing::Pimpl -{ - Pimpl() : oldIoPrio() {} - int oldIoPrio; -}; - - -ScheduleForBackgroundProcessing::ScheduleForBackgroundProcessing() : pimpl(make_unique<Pimpl>()) -{ - pimpl->oldIoPrio = ::getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS); - if (pimpl->oldIoPrio == -1) - throwFileError(_("Cannot change process I/O priorities."), L"getiopolicy_np", getLastError()); - - if (::setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE) != 0) - throwFileError(_("Cannot change process I/O priorities."), L"setiopolicy_np", getLastError()); -} - - -ScheduleForBackgroundProcessing::~ScheduleForBackgroundProcessing() -{ - ::setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, pimpl->oldIoPrio); -} #endif diff --git a/zen/process_priority.h b/zen/process_priority.h index 78e49cd0..a133985f 100644 --- a/zen/process_priority.h +++ b/zen/process_priority.h @@ -3,11 +3,11 @@ // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef PREVENTSTANDBY_H_INCLUDED -#define PREVENTSTANDBY_H_INCLUDED +#ifndef PREVENTSTANDBY_H_83421759082143245 +#define PREVENTSTANDBY_H_83421759082143245 #include <memory> -#include <zen/file_error.h> +#include "file_error.h" namespace zen { @@ -34,4 +34,4 @@ private: }; } -#endif // PREVENTSTANDBY_H_INCLUDED +#endif //PREVENTSTANDBY_H_83421759082143245 diff --git a/zen/recycler.cpp b/zen/recycler.cpp index 41ea6002..930b05ac 100644 --- a/zen/recycler.cpp +++ b/zen/recycler.cpp @@ -84,20 +84,21 @@ void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::func if (vistaOrLater()) //new recycle bin usage: available since Vista { - using namespace fileop; - const DllFun<FunType_moveToRecycleBin > moveToRecycler (getDllName(), funName_moveToRecycleBin); - const DllFun<FunType_getLastErrorMessage> getLastErrorMessage(getDllName(), funName_getLastErrorMessage); +#define DEF_DLL_FUN(name) const DllFun<fileop::FunType_##name> name(fileop::getDllName(), fileop::funName_##name); +DEF_DLL_FUN(moveToRecycleBin); +DEF_DLL_FUN(getLastErrorMessage); +#undef DEF_DLL_FUN - if (!moveToRecycler || !getLastErrorMessage) + if (!moveToRecycleBin || !getLastErrorMessage) throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtFileName(itempaths[0])), - replaceCpy(_("Cannot load file %x."), L"%x", fmtFileName(getDllName()))); + replaceCpy(_("Cannot load file %x."), L"%x", fmtFileName(fileop::getDllName()))); std::vector<const wchar_t*> cNames; for (auto it = itempaths.begin(); it != itempaths.end(); ++it) //CAUTION: do not create temporary strings here!! cNames.push_back(it->c_str()); CallbackData cbd(notifyDeletionStatus); - if (!moveToRecycler(&cNames[0], cNames.size(), onRecyclerCallback, &cbd)) + if (!moveToRecycleBin(&cNames[0], cNames.size(), onRecyclerCallback, &cbd)) { if (cbd.exceptionInUserCallback) { diff --git a/zen/tick_count.h b/zen/tick_count.h index cb15fe20..482689d7 100644 --- a/zen/tick_count.h +++ b/zen/tick_count.h @@ -102,7 +102,7 @@ int64_t ticksPerSec() //return 0 on error #ifdef ZEN_WIN LARGE_INTEGER frequency = {}; if (!::QueryPerformanceFrequency(&frequency)) //MSDN promises: "The frequency cannot change while the system is running." - return 0; + return 0; //MSDN: "This won't occur on any system that runs Windows XP or later." static_assert(sizeof(int64_t) >= sizeof(frequency.QuadPart), ""); return frequency.QuadPart; @@ -126,8 +126,10 @@ TickVal getTicks() //return !isValid() on error { #ifdef ZEN_WIN LARGE_INTEGER now = {}; - if (!::QueryPerformanceCounter(&now)) //msdn: SetThreadAffinityMask() may be required if there are bugs in BIOS or HAL" + if (!::QueryPerformanceCounter(&now)) return TickVal(); + //detailed info about QPC: http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx + //- MSDN: "No need to set the thread affinity" #elif defined ZEN_LINUX //gettimeofday() seems fine but is deprecated diff --git a/zen/type_traits.h b/zen/type_traits.h index 1c2da5eb..8e85a7b2 100644 --- a/zen/type_traits.h +++ b/zen/type_traits.h @@ -7,7 +7,7 @@ #ifndef TYPE_TRAITS_HEADER_3425628658765467 #define TYPE_TRAITS_HEADER_3425628658765467 -#include <type_traits> //all we need is std::is_class!! +#include <type_traits> //all we need is std::is_class!! namespace zen { @@ -38,10 +38,10 @@ struct ResultType //Herb Sutter's signedness conversion helpers: http://herbsutter.com/2013/06/13/gotw-93-solution-auto-variables-part-2/ template<class T> inline -typename std::make_signed<T>::type makeSigned(T t) { return std::make_signed<T>::type(t); } +typename std::make_signed<T>::type makeSigned(T t) { return typename std::make_signed<T>::type(t); } template<class T> inline -typename std::make_unsigned<T>::type makeUnsigned(T t) { return std::make_unsigned<T>::type(t); } +typename std::make_unsigned<T>::type makeUnsigned(T t) { return typename std::make_unsigned<T>::type(t); } //################# Built-in Types ######################## //Example: "IsSignedInt<int>::value" evaluates to "true" diff --git a/zen/zstring.cpp b/zen/zstring.cpp index f1858efc..f16af6a0 100644 --- a/zen/zstring.cpp +++ b/zen/zstring.cpp @@ -18,6 +18,7 @@ #ifndef NDEBUG #include <mutex> #include <iostream> +#include "thread.h" #endif using namespace zen; @@ -38,14 +39,14 @@ public: void insert(const void* ptr, size_t size) { - std::lock_guard<std::mutex> dummy(lockActStrings); + boost::lock_guard<boost::mutex> dummy(lockActStrings); if (!activeStrings.insert(std::make_pair(ptr, size)).second) reportProblem("Serious Error: New memory points into occupied space: " + rawMemToString(ptr, size)); } void remove(const void* ptr) { - std::lock_guard<std::mutex> dummy(lockActStrings); + boost::lock_guard<boost::mutex> dummy(lockActStrings); if (activeStrings.erase(ptr) != 1) reportProblem("Serious Error: No memory available for deallocation at this location!"); } @@ -94,7 +95,7 @@ private: throw std::logic_error("Memory leak! " + message); } - std::mutex lockActStrings; + boost::mutex lockActStrings; zen::hash_map<const void*, size_t> activeStrings; }; |