summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:16:21 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:16:21 +0200
commit88a2d0007db222c339f0b6a17794a2014a241892 (patch)
tree75105ef49b3a52b7ee176a1ad480e7652e49825f /lib
parent4.2 (diff)
downloadFreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.tar.gz
FreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.tar.bz2
FreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.zip
4.3
Diffstat (limited to 'lib')
-rw-r--r--lib/FindFilePlus/FindFilePlus.vcxproj245
-rw-r--r--lib/FindFilePlus/dll_main.cpp30
-rw-r--r--lib/FindFilePlus/find_file_plus.cpp298
-rw-r--r--lib/FindFilePlus/find_file_plus.h78
-rw-r--r--lib/FindFilePlus/init_dll_binding.h16
-rw-r--r--lib/FindFilePlus/load_dll.cpp23
-rw-r--r--lib/FindFilePlus/load_dll.h46
-rw-r--r--lib/custom_grid.cpp169
-rw-r--r--lib/db_file.cpp476
-rw-r--r--lib/db_file.h5
-rw-r--r--lib/detect_renaming.cpp285
-rw-r--r--lib/detect_renaming.h26
-rw-r--r--lib/dir_exist_async.h4
-rw-r--r--lib/dir_lock.cpp16
-rw-r--r--lib/dir_name.cpp2
-rw-r--r--lib/localization.cpp1
-rw-r--r--lib/parallel_scan.cpp15
-rw-r--r--lib/status_handler.h18
18 files changed, 327 insertions, 1426 deletions
diff --git a/lib/FindFilePlus/FindFilePlus.vcxproj b/lib/FindFilePlus/FindFilePlus.vcxproj
deleted file mode 100644
index 2c4256a6..00000000
--- a/lib/FindFilePlus/FindFilePlus.vcxproj
+++ /dev/null
@@ -1,245 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{70394AEF-5897-4911-AFA1-82EAF0581EFA}</ProjectGuid>
- <RootNamespace>ShadowDll</RootNamespace>
- <Keyword>Win32Proj</Keyword>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>Windows7.1SDK</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>Windows7.1SDK</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>Windows7.1SDK</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>Windows7.1SDK</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">FindFilePlus_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FindFilePlus_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FindFilePlus_$(Platform)</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">FindFilePlus_$(Platform)</TargetName>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">D:\Data\WinDDK\inc\ddk;D:\Data\WinDDK\inc\api;D:\Data\WinDDK\inc\crt;$(WindowsSdkDir)\include;$(VCInstallDir)include</IncludePath>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <BuildLog>
- <Path>$(IntDir)Build.html</Path>
- </BuildLog>
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_X86_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <DisableSpecificWarnings>4100</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
- <SubSystem>Windows</SubSystem>
- <ProfileGuidedDatabase>
- </ProfileGuidedDatabase>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <TargetMachine>MachineX86</TargetMachine>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <BuildLog>
- <Path>$(IntDir)Build.html</Path>
- </BuildLog>
- <Midl>
- <TargetEnvironment>X64</TargetEnvironment>
- </Midl>
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_AMD64_;_DEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4100</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
- <SubSystem>Windows</SubSystem>
- <ProfileGuidedDatabase>
- </ProfileGuidedDatabase>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <TargetMachine>MachineX64</TargetMachine>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <BuildLog>
- <Path>$(IntDir)Build.html</Path>
- </BuildLog>
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>_X86_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4100</DisableSpecificWarnings>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <ProfileGuidedDatabase>
- </ProfileGuidedDatabase>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <TargetMachine>MachineX86</TargetMachine>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <BuildLog>
- <Path>$(IntDir)Build.html</Path>
- </BuildLog>
- <Midl>
- <TargetEnvironment>X64</TargetEnvironment>
- </Midl>
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FIND_FILE_PLUS_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <DisableSpecificWarnings>4100</DisableSpecificWarnings>
- <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>false</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- <ProfileGuidedDatabase>
- </ProfileGuidedDatabase>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <TargetMachine>MachineX64</TargetMachine>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="dll_main.cpp">
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- </PrecompiledHeader>
- <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- </PrecompiledHeader>
- <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- </PrecompiledHeader>
- <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- </PrecompiledHeader>
- <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
- </ClCompile>
- <ClCompile Include="find_file_plus.cpp" />
- <ClCompile Include="load_dll.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="find_file_plus.h" />
- <ClInclude Include="load_dll.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/lib/FindFilePlus/dll_main.cpp b/lib/FindFilePlus/dll_main.cpp
deleted file mode 100644
index 5d64181b..00000000
--- a/lib/FindFilePlus/dll_main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-
-#define WIN32_LEAN_AND_MEAN
-#include <zen/win.h>
-
-#include "init_dll_binding.h"
-
-
-//optional: add init/teardown logic here
-BOOL APIENTRY DllMain(HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved)
-{
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- if (!findplus::initDllBinding())
- return false;
- case DLL_PROCESS_DETACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return true;
-}
diff --git a/lib/FindFilePlus/find_file_plus.cpp b/lib/FindFilePlus/find_file_plus.cpp
deleted file mode 100644
index becfe553..00000000
--- a/lib/FindFilePlus/find_file_plus.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "find_file_plus.h"
-#include "init_dll_binding.h"
-//#include <windows.h> //these two don't play nice with each other
-#include "load_dll.h"
-#include <zen/scope_guard.h>
-
-using namespace dll;
-using namespace findplus;
-
-
-namespace
-{
-struct FileError
-{
- FileError(ULONG errorCode) : win32Error(errorCode) {}
- ULONG win32Error;
-};
-
-
-//--------------------------------------------------------------------------------------------------------------
-typedef NTSTATUS (NTAPI* NtOpenFileFunc)(PHANDLE fileHandle,
- ACCESS_MASK desiredAccess,
- POBJECT_ATTRIBUTES objectAttributes,
- PIO_STATUS_BLOCK ioStatusBlock,
- ULONG shareAccess,
- ULONG openOptions);
-
-typedef NTSTATUS (NTAPI* NtCloseFunc)(HANDLE handle);
-
-typedef NTSTATUS (NTAPI* NtQueryDirectoryFileFunc)(HANDLE fileHandle,
- HANDLE event,
- PIO_APC_ROUTINE apcRoutine,
- PVOID apcContext,
- PIO_STATUS_BLOCK ioStatusBlock,
- PVOID fileInformation,
- ULONG length,
- FILE_INFORMATION_CLASS fileInformationClass,
- BOOLEAN ReturnSingleEntry,
- PUNICODE_STRING fileMask,
- BOOLEAN restartScan);
-
-typedef ULONG (NTAPI* RtlNtStatusToDosErrorFunc)(NTSTATUS /*__in status*/);
-
-typedef struct _RTL_RELATIVE_NAME_U
-{
- UNICODE_STRING RelativeName;
- HANDLE ContainingDirectory;
- PVOID /*PRTLP_CURDIR_REF*/ CurDirRef;
-} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U;
-
-typedef BOOLEAN (NTAPI* RtlDosPathNameToNtPathName_UFunc)(PCWSTR, //__in dosFileName,
- PUNICODE_STRING, //__out ntFileName,
- PCWSTR*, //__out_optFilePart,
- PRTL_RELATIVE_NAME_U); //__out_opt relativeName
-
-typedef BOOLEAN (NTAPI* RtlDosPathNameToRelativeNtPathName_UFunc)(PCWSTR, //__in dosFileName,
- PUNICODE_STRING, //__out ntFileName,
- PCWSTR*, //__out_optFilePart,
- PRTL_RELATIVE_NAME_U); //__out_opt relativeName
-
-typedef VOID (NTAPI* RtlFreeUnicodeStringFunc)(PUNICODE_STRING); //__inout unicodeString
-
-//--------------------------------------------------------------------------------------------------------------
-
-//it seems we cannot use any of the ntoskrnl.lib files in WinDDK as they produce access violations
-//fortunately dynamic binding works fine:
-const SysDllFun<NtOpenFileFunc> ntOpenFile (L"ntdll.dll", "NtOpenFile");
-const SysDllFun<NtCloseFunc> ntClose (L"ntdll.dll", "NtClose");
-const SysDllFun<NtQueryDirectoryFileFunc> ntQueryDirectoryFile (L"ntdll.dll", "NtQueryDirectoryFile");
-const SysDllFun<RtlNtStatusToDosErrorFunc> rtlNtStatusToDosError (L"ntdll.dll", "RtlNtStatusToDosError");
-const SysDllFun<RtlFreeUnicodeStringFunc> rtlFreeUnicodeString (L"ntdll.dll", "RtlFreeUnicodeString");
-const SysDllFun<RtlDosPathNameToNtPathName_UFunc> rtlDosPathNameToNtPathName_U(SysDllFun<RtlDosPathNameToRelativeNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToRelativeNtPathName_U") ?
- SysDllFun<RtlDosPathNameToRelativeNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToRelativeNtPathName_U") : //use the newer version if available
- SysDllFun<RtlDosPathNameToNtPathName_UFunc>(L"ntdll.dll", "RtlDosPathNameToNtPathName_U")); //fallback for XP
-//global constants only -> preserve thread safety!
-}
-
-
-bool findplus::initDllBinding() //evaluate in ::DllMain() when attaching process
-{
- //NT/ZwXxx Routines
- //http://msdn.microsoft.com/en-us/library/ff567122(v=VS.85).aspx
-
- //Run-Time Library (RTL) Routines
- //http://msdn.microsoft.com/en-us/library/ff563638(v=VS.85).aspx
-
- //verify dynamic dll binding
- return ntOpenFile &&
- ntClose &&
- ntQueryDirectoryFile &&
- rtlNtStatusToDosError &&
- rtlFreeUnicodeString &&
- rtlDosPathNameToNtPathName_U;
-
- //this may become handy some time: nt status code STATUS_ORDINAL_NOT_FOUND maps to win32 code ERROR_INVALID_ORDINAL
-}
-
-
-class findplus::FileSearcher
-{
-public:
- FileSearcher(const wchar_t* dirname); //throw FileError
- ~FileSearcher();
-
- void readdir(FileInformation& output); //throw FileError
-
-private:
- UNICODE_STRING ntPathName; //it seems hDir implicitly keeps a reference to this, at least ::FindFirstFile() does no cleanup before ::FindClose()!
- HANDLE hDir;
-
- ULONG nextEntryOffset; //!= 0 if entry is waiting in buffer
- //::FindNextFileW() uses 0x1000 = 4096 = sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * 2000
- //=> let's use the same, even if our header is 16 byte larger; maybe there is some packet size advantage for networks? Note that larger buffers seem to degrade performance.
- static const ULONG BUFFER_SIZE = 4096;
- LONGLONG buffer[BUFFER_SIZE / sizeof(LONGLONG)]; //buffer needs to be aligned at LONGLONG boundary
-
- static_assert(BUFFER_SIZE % sizeof(LONGLONG) == 0, "ups, our buffer is trimmed!");
-};
-
-
-FileSearcher::FileSearcher(const wchar_t* dirname) :
- hDir(NULL),
- nextEntryOffset(0)
-{
- ntPathName.Buffer = NULL;
- ntPathName.Length = 0;
- ntPathName.MaximumLength = 0;
-
- zen::ScopeGuard guardConstructor = zen::makeGuard([&]() { this->~FileSearcher(); });
- //--------------------------------------------------------------------------------------------------------------
-
- //convert dosFileName, e.g. C:\Users or \\?\C:\Users to ntFileName \??\C:\Users
- //in contrast to ::FindFirstFile() we don't evaluate the relativeName, however tests indicate ntFileName is *always* filled with an absolute name, even if dosFileName is relative
-
- //NOTE: RtlDosPathNameToNtPathName_U may be used on all XP/Win7/Win8 for compatibility
- // RtlDosPathNameToNtPathName_U: used by Windows XP available with OS version 3.51 (Windows NT) and higher
- // RtlDosPathNameToRelativeNtPathName_U: used by Win7/Win8 available with OS version 5.2 (Windows Server 2003) and higher
- if (!rtlDosPathNameToNtPathName_U(dirname, //__in dosFileName,
- &ntPathName, //__out ntFileName,
- NULL, //__out_optFilePart,
- NULL)) //__out_opt relativeName - empty if dosFileName is absolute
- throw FileError(rtlNtStatusToDosError(STATUS_OBJECT_PATH_NOT_FOUND)); //translates to ERROR_PATH_NOT_FOUND, same behavior like ::FindFirstFileEx()
-
- OBJECT_ATTRIBUTES objAttr = {};
- InitializeObjectAttributes(&objAttr, //[out] POBJECT_ATTRIBUTES initializedAttributes,
- &ntPathName, //[in] PUNICODE_STRING objectName,
- OBJ_CASE_INSENSITIVE, //[in] ULONG attributes,
- NULL, //[in] HANDLE rootDirectory,
- NULL); //[in, optional] PSECURITY_DESCRIPTOR securityDescriptor
-
- {
- IO_STATUS_BLOCK status = {};
- NTSTATUS rv = ntOpenFile(&hDir, //__out PHANDLE FileHandle,
- FILE_LIST_DIRECTORY | SYNCHRONIZE, //__in ACCESS_MASK desiredAccess, - 100001 used by ::FindFirstFile() on all XP/Win7/Win8
- &objAttr, //__in POBJECT_ATTRIBUTES objectAttributes,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //__in ULONG shareAccess, - 7 on Win7/Win8, 3 on XP
- FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); //__in ULONG openOptions - 4021 used on all XP/Win7/Win8
- if (!NT_SUCCESS(rv))
- throw FileError(rtlNtStatusToDosError(rv));
- }
-
- guardConstructor.dismiss();
-}
-
-
-inline
-FileSearcher::~FileSearcher()
-{
- //cleanup in reverse order
- if (hDir)
- ntClose(hDir);
-
- if (ntPathName.Buffer)
- rtlFreeUnicodeString(&ntPathName); //cleanup identical to ::FindFirstFile()
- //note that most if this function seems inlined by the linker, so that its assembly looks equivalent to "RtlFreeHeap(GetProcessHeap(), 0, ntPathName.Buffer)"
-}
-
-
-void FileSearcher::readdir(FileInformation& output)
-{
- //although FILE_ID_FULL_DIR_INFORMATION should suffice for our purposes, there are problems on Windows XP for certain directories, e.g. "\\Vboxsvr\build"
- //making NtQueryDirectoryFile() return with STATUS_INVALID_PARAMETER while other directories, e.g. "C:\" work fine for some reason
- //FILE_ID_BOTH_DIR_INFORMATION on the other hand works on XP/Win7/Win8
- //performance: there is no noticable difference between FILE_ID_BOTH_DIR_INFORMATION and FILE_ID_FULL_DIR_INFORMATION
-
- /* corresponding first access in ::FindFirstFileW()
-
- NTSTATUS rv = ntQueryDirectoryFile(hDir, //__in HANDLE fileHandle,
- NULL, //__in_opt HANDLE event,
- NULL, //__in_opt PIO_APC_ROUTINE apcRoutine,
- NULL, //__in_opt PVOID apcContext,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- &buffer, //__out_bcount(Length) PVOID fileInformation,
- BUFFER_SIZE, //__in ULONG length, ::FindFirstFileW() on all XP/Win7/Win8 uses sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * MAX_PATH == 0x268
- FileIdBothDirectoryInformation, //__in FILE_INFORMATION_CLASS fileInformationClass - all XP/Win7/Win8 use "FileBothDirectoryInformation"
- true, //__in BOOLEAN returnSingleEntry,
- NULL, //__in_opt PUNICODE_STRING mask,
- false); //__in BOOLEAN restartScan
- */
-
- //analog to ::FindNextFileW() with performance optimized access (in contrast to first access in ::FindFirstFileW())
- if (nextEntryOffset == 0)
- {
- IO_STATUS_BLOCK status = {};
- NTSTATUS rv = ntQueryDirectoryFile(hDir, //__in HANDLE fileHandle,
- NULL, //__in_opt HANDLE event,
- NULL, //__in_opt PIO_APC_ROUTINE apcRoutine,
- NULL, //__in_opt PVOID apcContext,
- &status, //__out PIO_STATUS_BLOCK ioStatusBlock,
- &buffer, //__out_bcount(Length) PVOID fileInformation,
- BUFFER_SIZE, //__in ULONG length, ::FindNextFileW() on all XP/Win7/Win8 uses sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(TCHAR) * 2000 == 0x1000
- FileIdBothDirectoryInformation, //__in FILE_INFORMATION_CLASS fileInformationClass - all XP/Win7/Win8 use "FileBothDirectoryInformation"
- false, //__in BOOLEAN returnSingleEntry,
- NULL, //__in_opt PUNICODE_STRING mask,
- false); //__in BOOLEAN restartScan
- if (!NT_SUCCESS(rv))
- throw FileError(rtlNtStatusToDosError(rv)); //throws STATUS_NO_MORE_FILES when finished
-
- if (status.Information == 0) //except for the first call to call ::NtQueryDirectoryFile():
- throw FileError(rtlNtStatusToDosError(STATUS_BUFFER_OVERFLOW)); //if buffer size is too small, return value is STATUS_SUCCESS and Information == 0 -> we don't expect this!
- }
-
- const FILE_ID_BOTH_DIR_INFORMATION& dirInfo = *reinterpret_cast<FILE_ID_BOTH_DIR_INFORMATION*>(reinterpret_cast<char*>(buffer) + nextEntryOffset);
-
- if (dirInfo.NextEntryOffset == 0)
- nextEntryOffset = 0; //our offset is relative to the beginning of the buffer
- else
- nextEntryOffset += dirInfo.NextEntryOffset;
-
-
- auto toFileTime = [](const LARGE_INTEGER & rawTime) -> FILETIME
- {
- FILETIME tmp = { rawTime.LowPart, rawTime.HighPart };
- return tmp;
- };
-
- output.creationTime = toFileTime(dirInfo.CreationTime);
- output.lastWriteTime = toFileTime(dirInfo.LastWriteTime);
- output.fileSize.QuadPart = dirInfo.EndOfFile.QuadPart;
- output.fileId.QuadPart = dirInfo.FileId.QuadPart;
- output.fileAttributes = dirInfo.FileAttributes;
- output.shortNameLength = dirInfo.FileNameLength / sizeof(TCHAR); //FileNameLength is in bytes!
-
- if (dirInfo.FileNameLength + sizeof(TCHAR) > sizeof(output.shortName)) //this may actually happen if ::NtQueryDirectoryFile() decides to return a
- throw FileError(rtlNtStatusToDosError(STATUS_BUFFER_OVERFLOW)); //short name of length MAX_PATH + 1, 0-termination is not required!
-
- ::memcpy(output.shortName, dirInfo.FileName, dirInfo.FileNameLength);
- output.shortName[output.shortNameLength] = 0; //NOTE: FILE_ID_BOTH_DIR_INFORMATION::FileName in general is NOT 0-terminated! It is on XP/Win7, but NOT on Win8!
-
- static_assert(sizeof(output.creationTime) == sizeof(dirInfo.CreationTime), "dang!");
- static_assert(sizeof(output.lastWriteTime) == sizeof(dirInfo.LastWriteTime), "dang!");
- static_assert(sizeof(output.fileSize) == sizeof(dirInfo.EndOfFile), "dang!");
- static_assert(sizeof(output.fileId) == sizeof(dirInfo.FileId), "dang!");
- static_assert(sizeof(output.fileAttributes) == sizeof(dirInfo.FileAttributes), "dang!");
-}
-
-
-FindHandle findplus::openDir(const wchar_t* dirname)
-{
- try
- {
- return new FileSearcher(dirname); //throw FileError
- }
- catch (const FileError& err)
- {
- setWin32Error(err.win32Error);
- return NULL;
- }
-}
-
-
-bool findplus::readDir(FindHandle hnd, FileInformation& output)
-{
- try
- {
- hnd->readdir(output); //throw FileError
- return true;
- }
- catch (const FileError& err)
- {
- setWin32Error(err.win32Error);
- return false;
- }
-}
-
-
-void findplus::closeDir(FindHandle hnd)
-{
- if (hnd) //play a little "nice"
- delete hnd;
-}
diff --git a/lib/FindFilePlus/find_file_plus.h b/lib/FindFilePlus/find_file_plus.h
deleted file mode 100644
index aacdf0ea..00000000
--- a/lib/FindFilePlus/find_file_plus.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef FIND_FIRST_FILE_PLUS_HEADER_087483434
-#define FIND_FIRST_FILE_PLUS_HEADER_087483434
-
-#ifdef FIND_FILE_PLUS_DLL_EXPORTS
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport)
-#else
-#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport)
-#endif
-
-
-#ifdef FIND_FILE_PLUS_DLL_EXPORTS
-#include <Ntifs.h> //driver level headers must be included *before* windows api headers!
-#endif
-#include <windef.h> //
-#undef min
-#undef max
-
-#include <zen/build_info.h>
-
-namespace findplus
-{
-/*--------------
- |declarations|
- --------------*/
-
-struct FileInformation
-{
- FILETIME creationTime;
- FILETIME lastWriteTime;
- ULARGE_INTEGER fileSize;
- ULARGE_INTEGER fileId;
- DWORD fileAttributes;
- DWORD shortNameLength;
- WCHAR shortName[MAX_PATH + 1]; //shortName is 0-terminated
-}; //no need for #pragma pack -> all members already starting at 4 byte boundary!
-
-class FileSearcher;
-typedef FileSearcher* FindHandle;
-
-DLL_FUNCTION_DECLARATION
-FindHandle openDir(const wchar_t* dirname); //returns NULL on error, call ::GetLastError()
-//note: do NOT place an asterisk at end, e.g. C:\SomeDir\*, as one would do for ::FindFirstFile()
-
-DLL_FUNCTION_DECLARATION
-bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES
-
-DLL_FUNCTION_DECLARATION
-void closeDir(FindHandle hnd);
-
-/*----------
- |typedefs|
- ----------*/
-typedef FindHandle (*OpenDirFunc )(const wchar_t* dirname);
-typedef bool (*ReadDirFunc )(FindHandle hnd, FileInformation& dirInfo);
-typedef void (*CloseDirFunc)(FindHandle hnd);
-
-/*--------------
- |symbol names|
- --------------*/
-//const pointers ensure internal linkage
-const char openDirFuncName [] = "openDir";
-const char readDirFuncName [] = "readDir";
-const char closeDirFuncName[] = "closeDir";
-
-/*---------------
- |library names|
- ---------------*/
-inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"FindFilePlus_x64.dll" : L"FindFilePlus_Win32.dll"; }
-}
-
-
-#endif //FIND_FIRST_FILE_PLUS_HEADER_087483434
diff --git a/lib/FindFilePlus/init_dll_binding.h b/lib/FindFilePlus/init_dll_binding.h
deleted file mode 100644
index 51b32c99..00000000
--- a/lib/FindFilePlus/init_dll_binding.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef INIT_DLL_BINDING_HEADER_ß018356031467832145
-#define INIT_DLL_BINDING_HEADER_ß018356031467832145
-
-namespace findplus
-{
-//load and check dll binding at startup
-bool initDllBinding(); //evaluate in ::DllMain() when attaching process
-}
-
-#endif //INIT_DLL_BINDING_HEADER_ß018356031467832145
diff --git a/lib/FindFilePlus/load_dll.cpp b/lib/FindFilePlus/load_dll.cpp
deleted file mode 100644
index 20d9a5fe..00000000
--- a/lib/FindFilePlus/load_dll.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "load_dll.h"
-#define WIN32_LEAN_AND_MEAN
-#include <zen/win.h>
-
-void* /*FARPROC*/ dll::loadSymbol(const wchar_t* libraryName, const char* functionName)
-{
- return ::GetProcAddress(::GetModuleHandle(libraryName), functionName);
- //cleanup neither required nor allowed (::FreeLibrary())
-
-}
-//note: void* and FARPROC function pointer have same binary size on Windows
-
-
-void dll::setWin32Error(unsigned long lastError)
-{
- ::SetLastError(lastError);
-}
diff --git a/lib/FindFilePlus/load_dll.h b/lib/FindFilePlus/load_dll.h
deleted file mode 100644
index 350de9f8..00000000
--- a/lib/FindFilePlus/load_dll.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef LOAD_DLL_HEADER_0312463214872163832174
-#define LOAD_DLL_HEADER_0312463214872163832174
-
-namespace dll
-{
-void setWin32Error(unsigned long lastError);
-
-//NOTE: uses ::GetModuleHandle => call for system DLLs only!
-template <class Func>
-class SysDllFun
-{
-public:
- SysDllFun(const wchar_t* systemLibrary, const char* functionName) :
- fun(reinterpret_cast<Func>(loadSymbol(systemLibrary, functionName))) {}
-
- operator Func() const { return fun; }
-
-private:
- Func fun;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-void* /*FARPROC*/ loadSymbol(const wchar_t* libraryName, const char* functionName);
-}
-
-#endif //LOAD_DLL_HEADER_0312463214872163832174
diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp
index 97db1676..f2892624 100644
--- a/lib/custom_grid.cpp
+++ b/lib/custom_grid.cpp
@@ -557,23 +557,24 @@ private:
case SO_CREATE_NEW_LEFT:
case SO_OVERWRITE_LEFT:
case SO_DELETE_LEFT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_COPY_METADATA_TO_LEFT:
result.first = *wxBLACK;
result.second = COLOR_SYNC_BLUE;
break;
- case SO_COPY_METADATA_TO_LEFT:
- result.first = *wxBLACK;
- result.second = COLOR_SYNC_BLUE_LIGHT;
+ // result.second = COLOR_SYNC_BLUE_LIGHT;
break;
case SO_CREATE_NEW_RIGHT:
case SO_OVERWRITE_RIGHT:
case SO_DELETE_RIGHT:
- result.first = *wxBLACK;
- result.second = COLOR_SYNC_GREEN;
- break;
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
case SO_COPY_METADATA_TO_RIGHT:
result.first = *wxBLACK;
- result.second = COLOR_SYNC_GREEN_LIGHT;
+ result.second = COLOR_SYNC_GREEN;
break;
+ // result.second = COLOR_SYNC_GREEN_LIGHT;
case SO_UNRESOLVED_CONFLICT:
result.first = *wxBLACK;
result.second = COLOR_YELLOW;
@@ -2038,70 +2039,77 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos)
if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview
{
- const SyncOperation syncOp = fsObj->getSyncOperation();
- switch (syncOp)
+ const wchar_t* imageName = [&]() -> const wchar_t*
{
- case SO_CREATE_NEW_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createLeft")));
- break;
- case SO_CREATE_NEW_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createRight")));
- break;
- case SO_DELETE_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteLeft")));
- break;
- case SO_DELETE_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteRight")));
- break;
- case SO_OVERWRITE_LEFT:
- case SO_COPY_METADATA_TO_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateLeft")));
- break;
- case SO_OVERWRITE_RIGHT:
- case SO_COPY_METADATA_TO_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateRight")));
- break;
- case SO_DO_NOTHING:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("none")));
- break;
- case SO_EQUAL:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("equal")));
- break;
- case SO_UNRESOLVED_CONFLICT:
- toolTip.show(fsObj->getSyncOpConflict(), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- };
+ const SyncOperation syncOp = fsObj->getSyncOperation();
+ switch (syncOp)
+ {
+ case SO_CREATE_NEW_LEFT:
+ return L"createLeft";
+ case SO_CREATE_NEW_RIGHT:
+ return L"createRight";
+ case SO_DELETE_LEFT:
+ return L"deleteLeft";
+ case SO_DELETE_RIGHT:
+ return L"deleteRight";
+ case SO_MOVE_LEFT_SOURCE:
+ return L"moveLeftSource";
+ case SO_MOVE_LEFT_TARGET:
+ return L"moveLeftTarget";
+ case SO_MOVE_RIGHT_SOURCE:
+ return L"moveRightSource";
+ case SO_MOVE_RIGHT_TARGET:
+ return L"moveRightTarget";
+ case SO_OVERWRITE_LEFT:
+ return L"updateLeft";
+ case SO_COPY_METADATA_TO_LEFT:
+ return L"moveLeft";
+ case SO_OVERWRITE_RIGHT:
+ return L"updateRight";
+ case SO_COPY_METADATA_TO_RIGHT:
+ return L"moveRight";
+ case SO_DO_NOTHING:
+ return L"none";
+ case SO_EQUAL:
+ return L"equal";
+ case SO_UNRESOLVED_CONFLICT:
+ return L"conflict";
+ };
+ assert(false);
+ return L"";
+ }();
+
+ toolTip.show(getSyncOpDescription(*fsObj), pos, &GlobalResources::getImage(imageName));
}
else
{
- const CompareFilesResult cmpRes = fsObj->getCategory();
- switch (cmpRes)
+ const wchar_t* imageName = [&]() -> const wchar_t*
{
- case FILE_LEFT_SIDE_ONLY:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftOnly")));
- break;
- case FILE_RIGHT_SIDE_ONLY:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightOnly")));
- break;
- case FILE_LEFT_NEWER:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftNewer")));
- break;
- case FILE_RIGHT_NEWER:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightNewer")));
- break;
- case FILE_DIFFERENT:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("different")));
- break;
- case FILE_EQUAL:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("equal")));
- break;
- case FILE_DIFFERENT_METADATA:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- case FILE_CONFLICT:
- toolTip.show(fsObj->getCatConflict(), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- }
+ const CompareFilesResult cmpRes = fsObj->getCategory();
+ switch (cmpRes)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ return L"leftOnly";
+ case FILE_RIGHT_SIDE_ONLY:
+ return L"rightOnly";
+ case FILE_LEFT_NEWER:
+ return L"leftNewer";
+ case FILE_RIGHT_NEWER:
+ return L"rightNewer";
+ case FILE_DIFFERENT:
+ return L"different";
+ case FILE_EQUAL:
+ return L"equal";
+ case FILE_DIFFERENT_METADATA:
+ return L"conflict";
+ case FILE_CONFLICT:
+ return L"conflict";
+ }
+ assert(false);
+ return L"";
+ }();
+
+ toolTip.show(getCategoryDescription(*fsObj), pos, &GlobalResources::getImage(imageName));
}
}
@@ -2284,6 +2292,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid,
//HIGHLIGHTNING (sync direction):
if (rowIsHighlighted &&
m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files
+
switch (m_gridMiddle.highlightedPos)
{
case CustomGridMiddle::BLOCKPOS_CHECK_BOX:
@@ -2374,25 +2383,35 @@ const wxBitmap& zen::getSyncOpImage(SyncOperation syncOp)
switch (syncOp) //evaluate comparison result and sync direction
{
case SO_CREATE_NEW_LEFT:
- return GlobalResources::getImage(wxT("createLeftSmall"));
+ return GlobalResources::getImage(L"createLeftSmall");
case SO_CREATE_NEW_RIGHT:
- return GlobalResources::getImage(wxT("createRightSmall"));
+ return GlobalResources::getImage(L"createRightSmall");
case SO_DELETE_LEFT:
- return GlobalResources::getImage(wxT("deleteLeftSmall"));
+ return GlobalResources::getImage(L"deleteLeftSmall");
case SO_DELETE_RIGHT:
- return GlobalResources::getImage(wxT("deleteRightSmall"));
+ return GlobalResources::getImage(L"deleteRightSmall");
+ case SO_MOVE_LEFT_SOURCE:
+ return GlobalResources::getImage(L"moveLeftSourceSmall");
+ case SO_MOVE_LEFT_TARGET:
+ return GlobalResources::getImage(L"moveLeftTargetSmall");
+ case SO_MOVE_RIGHT_SOURCE:
+ return GlobalResources::getImage(L"moveRightSourceSmall");
+ case SO_MOVE_RIGHT_TARGET:
+ return GlobalResources::getImage(L"moveRightTargetSmall");
case SO_OVERWRITE_RIGHT:
+ return GlobalResources::getImage(L"updateRightSmall");
case SO_COPY_METADATA_TO_RIGHT:
- return GlobalResources::getImage(wxT("updateRightSmall"));
+ return GlobalResources::getImage(L"moveRightSmall");
case SO_OVERWRITE_LEFT:
+ return GlobalResources::getImage(L"updateLeftSmall");
case SO_COPY_METADATA_TO_LEFT:
- return GlobalResources::getImage(wxT("updateLeftSmall"));
+ return GlobalResources::getImage(L"moveLeftSmall");
case SO_DO_NOTHING:
- return GlobalResources::getImage(wxT("noneSmall"));
+ return GlobalResources::getImage(L"noneSmall");
case SO_EQUAL:
- return GlobalResources::getImage(wxT("equalSmall"));
+ return GlobalResources::getImage(L"equalSmall");
case SO_UNRESOLVED_CONFLICT:
- return GlobalResources::getImage(wxT("conflictSmall"));
+ return GlobalResources::getImage(L"conflictSmall");
}
return wxNullBitmap; //dummy
diff --git a/lib/db_file.cpp b/lib/db_file.cpp
index faee4c8a..60a721b1 100644
--- a/lib/db_file.cpp
+++ b/lib/db_file.cpp
@@ -15,7 +15,7 @@
#include <zen/file_io.h>
#include <zen/scope_guard.h>
#include <zen/guid.h>
-#include <boost/bind.hpp>
+#include <zen/utf8.h>
#ifdef FFS_WIN
#include <zen/win.h> //includes "windows.h"
@@ -29,15 +29,24 @@ namespace
{
//-------------------------------------------------------------------------------------------------------------------------------
const char FILE_FORMAT_DESCR[] = "FreeFileSync";
-const int FILE_FORMAT_VER = 7;
+const int FILE_FORMAT_VER = 8;
//-------------------------------------------------------------------------------------------------------------------------------
+typedef std::string UniqueId;
+typedef Zbase<char> MemoryStream; //ref-counted byte stream representing DirInformation
+typedef std::map<UniqueId, MemoryStream> StreamMapping; //list of streams ordered by session UUID
+
+
+//------------------------------------------------------------------------------------
+//| ensure 32/64 bit portability: used fixed size data types only e.g. std::uint32_t |
+//------------------------------------------------------------------------------------
+
template <SelectedSide side> inline
Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false)
{
- //Linux and Windows builds are binary incompatible: char/wchar_t case, sensitive/insensitive
- //32 and 64 bit db files ARE designed to be binary compatible!
+ //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity?
+ //however 32 and 64 bit db files *are* designed to be binary compatible!
//Give db files different names.
//make sure they end with ".ffs_db". These files will not be included into comparison when located in base sync directories
#ifdef FFS_WIN
@@ -51,255 +60,209 @@ Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false)
}
-
-class FileInputStreamDB : public FileInputStream
+StreamMapping loadStreams(const Zstring& filename) //throw FileError
{
-public:
- FileInputStreamDB(const Zstring& filename) : //throw FileError
- FileInputStream(filename)
+ if (!zen::fileExists(filename))
+ throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
+ _("One of the FreeFileSync database files is not yet existing:") + L" \n" +
+ L"\"" + filename + L"\"");
+ try
{
+ //read format description (uncompressed)
+ FileInputStream rawStream(filename); //throw FileError
+
//read FreeFileSync file identifier
char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {};
- Read(formatDescr, sizeof(formatDescr)); //throw FileError
+ rawStream.Read(formatDescr, sizeof(formatDescr)); //throw FileError
if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr))
throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
- }
-private:
-};
+ wxZlibInputStream decompressed(rawStream, wxZLIB_ZLIB);
+ CheckedReader cr(decompressed, filename);
-class FileOutputStreamDB : public FileOutputStream
-{
-public:
- FileOutputStreamDB(const Zstring& filename) : //throw FileError
- FileOutputStream(filename)
+ std::int32_t version = cr.readNumberC<std::int32_t>();
+ if (version != FILE_FORMAT_VER) //read file format version#
+ throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
+
+ //read stream lists
+ StreamMapping output;
+
+ std::uint32_t dbCount = cr.readNumberC<std::uint32_t>(); //number of databases: one for each sync-pair
+ while (dbCount-- != 0)
+ {
+ //DB id of partner databases
+ const std::string sessionID = cr.readStringC<std::string>();
+ const MemoryStream stream = cr.readStringC<MemoryStream>(); //read db-entry stream (containing DirInformation)
+
+ output.insert(std::make_pair(sessionID, stream));
+ }
+ return output;
+ }
+ catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
{
- //write FreeFileSync file identifier
- Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError
+ throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)");
}
-
-private:
-};
}
-//#######################################################################################################################################
-class ReadDirInfo : public zen::ReadInputStream
+class StreamParser : private CheckedReader
{
public:
- ReadDirInfo(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName)
+ static DirInfoPtr execute(const MemoryStream& stream, const Zstring& fileName) //throw FileError -> return value always bound!
{
- //|-------------------------------------------------------------------------------------
- //| ensure 32/64 bit portability: use fixed size data types only e.g. boost::uint32_t |
- //|-------------------------------------------------------------------------------------
-
- //read filter settings -> currently not required, but persisting it doesn't hurt
- dirInfo.filter = HardFilter::loadFilter(getStream());
- check();
-
- //start recursion
- execute(dirInfo.baseDirContainer);
+ try
+ {
+ //read streams into DirInfo
+ auto dirInfo = std::make_shared<DirInformation>();
+ wxMemoryInputStream buffer(&*stream.begin(), stream.size()); //convert char-array to inputstream: no copying, ownership not transferred
+ StreamParser(buffer, fileName, *dirInfo); //throw FileError
+ return dirInfo;
+ }
+ catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
+ {
+ throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)");
+ }
}
private:
- void execute(DirContainer& dirCont) const
+ StreamParser(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : CheckedReader(stream, errorObjName)
{
- while (readNumberC<bool>())
- readSubFile(dirCont);
-
- while (readNumberC<bool>())
- readSubLink(dirCont);
-
- while (readNumberC<bool>())
- readSubDirectory(dirCont);
+ recurse(dirInfo.baseDirContainer);
}
- void readSubFile(DirContainer& dirCont) const
+ Zstring readStringUtf8() const
{
- //attention: order of function argument evaluation is undefined! So do it one after the other...
- const Zstring shortName = readStringC<Zstring>(); //file name
-
- const std::int64_t modTime = readNumberC<std::int64_t>();
- const std::uint64_t fileSize = readNumberC<std::uint64_t>();
-
- //const util::FileID fileIdentifier(stream_);
- //check();
-
- dirCont.addSubFile(shortName,
- FileDescriptor(modTime, fileSize));
+ return utf8CvrtTo<Zstring>(readStringC<Zbase<char>>());
}
-
- void readSubLink(DirContainer& dirCont) const
+ FileId readFileId() const
{
- //attention: order of function argument evaluation is undefined! So do it one after the other...
- const Zstring shortName = readStringC<Zstring>(); //file name
- const std::int64_t modTime = readNumberC<std::int64_t>();
- const Zstring targetPath = readStringC<Zstring>(); //file name
- const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>());
-
- dirCont.addSubLink(shortName,
- LinkDescriptor(modTime, targetPath, linkType));
- }
+ assert_static(sizeof(FileId().first ) <= sizeof(std::uint64_t));
+ assert_static(sizeof(FileId().second) <= sizeof(std::uint64_t));
-
- void readSubDirectory(DirContainer& dirCont) const
- {
- const Zstring shortName = readStringC<Zstring>(); //directory name
- DirContainer& subDir = dirCont.addSubDir(shortName);
- execute(subDir); //recurse
+ const auto devId = static_cast<decltype(FileId().first )>(readNumberC<std::uint64_t>()); //
+ const auto fId = static_cast<decltype(FileId().second)>(readNumberC<std::uint64_t>()); //silence "loss of precision" compiler warnings
+ return std::make_pair(devId, fId);
}
-};
-namespace
-{
-typedef std::string UniqueId;
-typedef std::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation
-typedef std::map<UniqueId, MemoryStreamPtr> StreamMapping; //list of streams ordered by session UUID
-}
-
-class ReadFileStream : public zen::ReadInputStream
-{
-public:
- ReadFileStream(wxInputStream& stream, const Zstring& filename, StreamMapping& streamList) : ReadInputStream(stream, filename)
+ void recurse(DirContainer& dirCont) const
{
- //|-------------------------------------------------------------------------------------
- //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t |
- //|-------------------------------------------------------------------------------------
-
- std::int32_t version = readNumberC<std::int32_t>();
+ while (readNumberC<bool>()) //files
+ {
+ //attention: order of function argument evaluation is undefined! So do it one after the other...
+ const Zstring shortName = readStringUtf8(); //file name
- if (version != FILE_FORMAT_VER) //read file format version
- throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
+ const std::int64_t modTime = readNumberC<std::int64_t>();
+ const std::uint64_t fileSize = readNumberC<std::uint64_t>();
+ const FileId fileID = readFileId();
- streamList.clear();
+ dirCont.addSubFile(shortName,
+ FileDescriptor(modTime, fileSize, fileID));
+ }
- boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair
- while (dbCount-- != 0)
+ while (readNumberC<bool>()) //symlinks
{
- //DB id of partner databases
- const CharArray tmp2 = readArrayC();
- const std::string sessionID(tmp2->begin(), tmp2->end());
-
- CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation)
+ //attention: order of function argument evaluation is undefined! So do it one after the other...
+ const Zstring shortName = readStringUtf8(); //file name
+ const std::int64_t modTime = readNumberC<std::int64_t>();
+ const Zstring targetPath = readStringUtf8(); //file name
+ const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>());
+
+ dirCont.addSubLink(shortName,
+ LinkDescriptor(modTime, targetPath, linkType));
+ }
- streamList.insert(std::make_pair(sessionID, buffer));
+ while (readNumberC<bool>()) //directories
+ {
+ const Zstring shortName = readStringUtf8(); //directory name
+ DirContainer& subDir = dirCont.addSubDir(shortName);
+ recurse(subDir);
}
}
};
-namespace
-{
-StreamMapping loadStreams(const Zstring& filename) //throw FileError
-{
- if (!zen::fileExists(filename))
- throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
- _("One of the FreeFileSync database files is not yet existing:") + L" \n" +
- L"\"" + filename + L"\"");
-
- try
- {
- //read format description (uncompressed)
- FileInputStreamDB uncompressed(filename); //throw FileError
-
- wxZlibInputStream input(uncompressed, wxZLIB_ZLIB);
- StreamMapping streamList;
- ReadFileStream(input, filename, streamList);
- return streamList;
- }
- catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
+//save/load DirContainer
+void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError
+{
{
- throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)");
- }
-}
+ FileOutputStream rawStream(filename); //throw FileError
+ //write FreeFileSync file identifier
+ rawStream.Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError
-DirInfoPtr parseStream(const std::vector<char>& stream, const Zstring& fileName) //throw FileError -> return value always bound!
-{
- try
- {
- //read streams into DirInfo
- auto dirInfo = std::make_shared<DirInformation>();
- wxMemoryInputStream buffer(&stream[0], stream.size()); //convert char-array to inputstream: no copying, ownership not transferred
- ReadDirInfo(buffer, fileName, *dirInfo); //throw FileError
- return dirInfo;
- }
- catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
- {
- throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)");
- }
-}
-}
+ wxZlibOutputStream compressed(rawStream, 4, wxZLIB_ZLIB);
+ /* 4 - best compromise between speed and compression: (scanning 200.000 objects)
+ 0 (uncompressed) 8,95 MB - 422 ms
+ 2 2,07 MB - 470 ms
+ 4 1,87 MB - 500 ms
+ 6 1,77 MB - 613 ms
+ 9 (maximal compression) 1,74 MB - 3330 ms */
+ CheckedWriter cw(compressed, filename);
-std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError
-{
- const Zstring fileNameLeft = getDBFilename<LEFT_SIDE>(baseMapping);
- const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping);
+ //save file format version
+ cw.writeNumberC<std::int32_t>(FILE_FORMAT_VER);
- //read file data: list of session ID + DirInfo-stream
- const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError
- const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError
+ //save stream list
+ cw.writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(streamList.size())); //number of database records: one for each sync-pair
- //find associated session: there can be at most one session within intersection of left and right ids
- StreamMapping::const_iterator streamLeft = streamListLeft .end();
- StreamMapping::const_iterator streamRight = streamListRight.end();
- for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft)
- {
- auto iterRight = streamListRight.find(iterLeft->first);
- if (iterRight != streamListRight.end())
+ for (auto iter = streamList.begin(); iter != streamList.end(); ++iter)
{
- streamLeft = iterLeft;
- streamRight = iterRight;
- break;
+ cw.writeStringC<std::string >(iter->first ); //sync session id
+ cw.writeStringC<MemoryStream>(iter->second); //DirInformation stream
}
}
-
- if (streamLeft == streamListLeft .end() ||
- streamRight == streamListRight.end() ||
- !streamLeft ->second.get() ||
- !streamRight->second.get())
- throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
- _("Database files do not share a common synchronization session:") + L" \n" +
- L"\"" + fileNameLeft + L"\"\n" +
- L"\"" + fileNameRight + L"\"");
- //read streams into DirInfo
- DirInfoPtr dirInfoLeft = parseStream(*streamLeft ->second, fileNameLeft); //throw FileError
- DirInfoPtr dirInfoRight = parseStream(*streamRight->second, fileNameRight); //throw FileError
-
- return std::make_pair(dirInfoLeft, dirInfoRight);
+ //(try to) hide database file
+#ifdef FFS_WIN
+ ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
+#endif
}
-//-------------------------------------------------------------------------------------------------------------------------
template <SelectedSide side>
-class SaveDirInfo : public WriteOutputStream
+class StreamGenerator : private CheckedWriter
{
public:
- SaveDirInfo(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream)
+ static MemoryStream execute(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName)
{
- //save filter settings
- baseMapping.getFilter()->saveFilter(getStream());
- check();
+ wxMemoryOutputStream buffer;
+ StreamGenerator(baseMapping, oldDirInfo, errorObjName, buffer);
- //start recursion
- execute(baseMapping, oldDirInfo);
+ MemoryStream output;
+ output.resize(buffer.GetSize());
+ buffer.CopyTo(&*output.begin(), buffer.GetSize());
+ return output;
}
private:
- void execute(const HierarchyObject& hierObj, const DirContainer* oldDirInfo)
+ StreamGenerator(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : CheckedWriter(stream, errorObjName)
+ {
+ recurse(baseMapping, oldDirInfo);
+ }
+
+ void recurse(const HierarchyObject& hierObj, const DirContainer* oldDirInfo)
{
- std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), boost::bind(&SaveDirInfo::processFile, this, _1, oldDirInfo));
+ // for (const auto& fileMap : hierObj.refSubFiles()) { processFile(fileMap, oldDirInfo); }); !
+
+ std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](const FileMapping& fileMap) { this->processFile(fileMap, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
- std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), boost::bind(&SaveDirInfo::processLink, this, _1, oldDirInfo));
+ std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), [&](const SymLinkMapping& linkObj) { this->processLink(linkObj, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
- std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), boost::bind(&SaveDirInfo::processDir, this, _1, oldDirInfo));
+ std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), [&](const DirMapping& dirMap) { this->processDir(dirMap, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
}
+ void writeStringUtf8(const Zstring& str) { writeStringC(utf8CvrtTo<Zbase<char>>(str)); }
+
+ void writeFileId(const FileId& id)
+ {
+ writeNumberC<std::uint64_t>(id.first ); //device id
+ writeNumberC<std::uint64_t>(id.second); //file id
+ }
+
void processFile(const FileMapping& fileMap, const DirContainer* oldParentDir)
{
if (fileMap.getCategory() == FILE_EQUAL) //data in sync: write current state
@@ -307,9 +270,10 @@ private:
if (!fileMap.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(fileMap.getShortName<side>()); //save respecting case! (Windows)
- writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>())); //last modification time
- writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>())); //filesize
+ writeStringUtf8(fileMap.getShortName<side>()); //save respecting case! (Windows)
+ writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>()));
+ writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>()));
+ writeFileId(fileMap.getFileId<side>());
}
}
else //not in sync: reuse last synchronous state
@@ -320,9 +284,10 @@ private:
if (iter != oldParentDir->files.end())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(iter->first); //save respecting case! (Windows)
- writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw)); //last modification time
- writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize)); //filesize
+ writeStringUtf8(iter->first); //save respecting case! (Windows)
+ writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw));
+ writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize));
+ writeFileId(iter->second.id);
}
}
}
@@ -335,9 +300,9 @@ private:
if (!linkObj.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(linkObj.getShortName<side>()); //save respecting case! (Windows)
- writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>())); //last modification time
- writeStringC(linkObj.getTargetPath<side>());
+ writeStringUtf8(linkObj.getShortName<side>()); //save respecting case! (Windows)
+ writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>()));
+ writeStringUtf8(linkObj.getTargetPath<side>());
writeNumberC<std::int32_t>(linkObj.getLinkType<side>());
}
}
@@ -349,9 +314,9 @@ private:
if (iter != oldParentDir->links.end())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(iter->first); //save respecting case! (Windows)
- writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw)); //last modification time
- writeStringC(iter->second.targetPath);
+ writeStringUtf8(iter->first); //save respecting case! (Windows)
+ writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw));
+ writeStringUtf8(iter->second.targetPath);
writeNumberC<std::int32_t>(iter->second.type);
}
}
@@ -379,8 +344,8 @@ private:
if (!dirMap.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(dirMap.getShortName<side>()); //save respecting case! (Windows)
- execute(dirMap, oldDir); //recurse
+ writeStringUtf8(dirMap.getShortName<side>()); //save respecting case! (Windows)
+ recurse(dirMap, oldDir);
}
}
else //not in sync: reuse last synchronous state
@@ -388,8 +353,8 @@ private:
if (oldDir)
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(*oldDirName); //save respecting case! (Windows)
- execute(dirMap, oldDir); //recurse
+ writeStringUtf8(*oldDirName); //save respecting case! (Windows)
+ recurse(dirMap, oldDir);
return;
}
//no data is also a "synchronous state"!
@@ -408,69 +373,53 @@ private:
break;
case DIR_DIFFERENT_METADATA:
writeNumberC<bool>(true);
- writeStringC(dirMap.getShortName<side>());
+ writeStringUtf8(dirMap.getShortName<side>());
//ATTENTION: strictly this is a violation of the principle of reporting last synchronous state!
//however in this case this will result in "last sync unsuccessful" for this directory within <automatic> algorithm, which is fine
- execute(dirMap, oldDir); //recurse and save sub-items which are in sync
+ recurse(dirMap, oldDir); //recurse and save sub-items which are in sync
break;
}
}
}
};
+}
+//#######################################################################################################################################
-class WriteFileStream : public WriteOutputStream
+std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError
{
-public:
- WriteFileStream(const StreamMapping& streamList, const Zstring& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream)
- {
- //save file format version
- writeNumberC<std::int32_t>(FILE_FORMAT_VER);
+ const Zstring fileNameLeft = getDBFilename<LEFT_SIDE >(baseMapping);
+ const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping);
- writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(streamList.size())); //number of database records: one for each sync-pair
+ //read file data: list of session ID + DirInfo-stream
+ const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError
+ const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError
- for (StreamMapping::const_iterator i = streamList.begin(); i != streamList.end(); ++i)
+ //find associated session: there can be at most one session within intersection of left and right ids
+ StreamMapping::const_iterator streamLeft = streamListLeft .end();
+ StreamMapping::const_iterator streamRight = streamListRight.end();
+ for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft)
+ {
+ auto iterRight = streamListRight.find(iterLeft->first);
+ if (iterRight != streamListRight.end())
{
- //sync session id
- writeArrayC(std::vector<char>(i->first.begin(), i->first.end()));
-
- //write DirInformation stream
- writeArrayC(*(i->second));
+ streamLeft = iterLeft;
+ streamRight = iterRight;
+ break;
}
}
-};
+ if (streamLeft == streamListLeft .end() ||
+ streamRight == streamListRight.end())
+ throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
+ _("Database files do not share a common synchronization session:") + L" \n" +
+ L"\"" + fileNameLeft + L"\"\n" +
+ L"\"" + fileNameRight + L"\"");
+ //read streams into DirInfo
+ DirInfoPtr dirInfoLeft = StreamParser::execute(streamLeft ->second, fileNameLeft); //throw FileError
+ DirInfoPtr dirInfoRight = StreamParser::execute(streamRight->second, fileNameRight); //throw FileError
-//save/load DirContainer
-void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError
-{
- {
- //write format description (uncompressed)
- FileOutputStreamDB uncompressed(filename); //throw FileError
-
- wxZlibOutputStream output(uncompressed, 4, wxZLIB_ZLIB);
- /* 4 - best compromise between speed and compression: (scanning 200.000 objects)
- 0 (uncompressed) 8,95 MB - 422 ms
- 2 2,07 MB - 470 ms
- 4 1,87 MB - 500 ms
- 6 1,77 MB - 613 ms
- 9 (maximal compression) 1,74 MB - 3330 ms */
-
- WriteFileStream(streamList, filename, output);
- }
- //(try to) hide database file
-#ifdef FFS_WIN
- ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
-#endif
-}
-
-
-bool equalEntry(const MemoryStreamPtr& lhs, const MemoryStreamPtr& rhs)
-{
- if (!lhs.get() || !rhs.get())
- return lhs.get() == rhs.get();
-
- return *lhs == *rhs;
+ return std::make_pair(dirInfoLeft, dirInfoRight);
}
@@ -522,12 +471,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
try
{
if (streamLeft != streamListLeft .end() &&
- streamRight != streamListRight.end() &&
- streamLeft ->second.get() &&
- streamRight->second.get())
+ streamRight != streamListRight.end())
{
- oldDirInfoLeft = parseStream(*streamLeft ->second, dbNameLeft); //throw FileError
- oldDirInfoRight = parseStream(*streamRight->second, dbNameRight); //throw FileError
+ oldDirInfoLeft = StreamParser::execute(streamLeft ->second, dbNameLeft ); //throw FileError
+ oldDirInfoRight = StreamParser::execute(streamRight->second, dbNameRight); //throw FileError
}
}
catch (FileError&)
@@ -538,28 +485,13 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
}
//create new database entries
- MemoryStreamPtr newStreamLeft = std::make_shared<std::vector<char>>();
- {
- wxMemoryOutputStream buffer;
- const DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL;
- SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, dbNameLeft, buffer);
- newStreamLeft->resize(buffer.GetSize()); //convert output stream to char-array
- buffer.CopyTo(&(*newStreamLeft)[0], buffer.GetSize()); //
- }
-
- MemoryStreamPtr newStreamRight = std::make_shared<std::vector<char>>();
- {
- wxMemoryOutputStream buffer;
- const DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL;
- SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, dbNameRight, buffer);
- newStreamRight->resize(buffer.GetSize()); //convert output stream to char-array
- buffer.CopyTo(&(*newStreamRight)[0], buffer.GetSize()); //
- }
+ MemoryStream newStreamLeft = StreamGenerator<LEFT_SIDE >::execute(baseMapping, oldDirInfoLeft .get() ? &oldDirInfoLeft ->baseDirContainer : NULL, dbNameLeft);
+ MemoryStream newStreamRight = StreamGenerator<RIGHT_SIDE>::execute(baseMapping, oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL, dbNameRight);
//check if there is some work to do at all
{
- const bool updateRequiredLeft = streamLeft == streamListLeft .end() || !equalEntry(newStreamLeft, streamLeft ->second);
- const bool updateRequiredRight = streamRight == streamListRight.end() || !equalEntry(newStreamRight, streamRight->second);
+ const bool updateRequiredLeft = streamLeft == streamListLeft .end() || newStreamLeft != streamLeft ->second;
+ const bool updateRequiredRight = streamRight == streamListRight.end() || newStreamRight != streamRight->second;
//some users monitor the *.ffs_db file with RTS => don't touch the file if it isnt't strictly needed
if (!updateRequiredLeft && !updateRequiredRight)
return;
@@ -579,10 +511,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
streamListRight.insert(std::make_pair(sessionID, newStreamRight));
//write (temp-) files...
- zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&]() {zen::removeFile(dbNameLeftTmp); });
+ zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&] {zen::removeFile(dbNameLeftTmp); });
saveFile(streamListLeft, dbNameLeftTmp); //throw FileError
- zen::ScopeGuard guardTempFileRight = zen::makeGuard([&]() {zen::removeFile(dbNameRightTmp); });
+ zen::ScopeGuard guardTempFileRight = zen::makeGuard([&] {zen::removeFile(dbNameRightTmp); });
saveFile(streamListRight, dbNameRightTmp); //throw FileError
//operation finished: rename temp files -> this should work transactionally:
diff --git a/lib/db_file.h b/lib/db_file.h
index d6d765cc..0413c404 100644
--- a/lib/db_file.h
+++ b/lib/db_file.h
@@ -14,11 +14,8 @@ namespace zen
{
const Zstring SYNC_DB_FILE_ENDING = Zstr(".ffs_db");
-void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError
-
struct DirInformation
{
- HardFilter::FilterRef filter; //filter settings (used when retrieving directory data)
DirContainer baseDirContainer; //hierarchical directory information
};
typedef std::shared_ptr<const DirInformation> DirInfoPtr;
@@ -26,6 +23,8 @@ typedef std::shared_ptr<const DirInformation> DirInfoPtr;
DEFINE_NEW_FILE_ERROR(FileErrorDatabaseNotExisting);
std::pair<DirInfoPtr, DirInfoPtr> loadFromDisk(const BaseDirMapping& baseMapping); //throw FileError, FileErrorDatabaseNotExisting -> return value always bound!
+
+void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError
}
#endif // DBFILE_H_INCLUDED
diff --git a/lib/detect_renaming.cpp b/lib/detect_renaming.cpp
deleted file mode 100644
index 39e7eb4b..00000000
--- a/lib/detect_renaming.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "detect_renaming.h"
-#include <map>
-#include <vector>
-#include <boost/bind.hpp>
-
-using namespace FreeFileSync;
-
-/*detect renamed files:
-Example:
- X -> |_| Create right
-|_| -> Y Delete right
-
-is detected as:
-
-Rename Y to X on right
-
-Algorithm:
-----------
-DB-file left ---filename, Metadata(=:MD)---> DB-file right
- /|\ |
- | fileID, MD
- fileID, MD |
- | \|/
- X Y
-
-*/
-
-
-class FindDBAssoc
-{
- /*
- load and associate db-files by filename and metadata(size, date)
- fileID, MD |-> fileID
- */
-public:
- struct AssocKey
- {
- AssocKey(const Utility::FileID& fileId,
- const wxLongLong& lastWriteTimeRaw,
- const wxULongLong& fileSize);
-
- bool operator<(const AssocKey& other) const;
-
- Utility::FileID fileId_;
- wxLongLong lastWriteTimeRaw_;
- wxULongLong fileSize_;
- };
-
- FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping,
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight);
-
-private:
- void recurse(const DirContainer& leftSide, const DirContainer& rightSide);
-
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight_; //-->
-};
-
-
-inline
-FindDBAssoc::AssocKey::AssocKey(const Utility::FileID& fileId,
- const wxLongLong& lastWriteTimeRaw,
- const wxULongLong& fileSize) :
- fileId_(fileId),
- lastWriteTimeRaw_(lastWriteTimeRaw),
- fileSize_(fileSize) {}
-
-
-inline
-bool FindDBAssoc::AssocKey::operator<(const AssocKey& other) const
-{
- if (fileId_ != other.fileId_)
- return fileId_ < other.fileId_;
-
- if (lastWriteTimeRaw_ != other.lastWriteTimeRaw_)
- return lastWriteTimeRaw_ < other.lastWriteTimeRaw_;
-
- return fileSize_ < other.fileSize_;
-}
-
-
-FindDBAssoc::FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping,
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight) : assocDBLeftToRight_(assocDBLeftToRight)
-{
- try
- {
- std::pair<FreeFileSync::DirInfoPtr, FreeFileSync::DirInfoPtr> dbInfo =
- FreeFileSync::loadFromDisk(baseMapping); //throw (FileError)
-
- recurse(dbInfo.first->baseDirContainer,
- dbInfo.second->baseDirContainer);
- }
- catch (...) {} //swallow...
-}
-
-
-void FindDBAssoc::recurse(const DirContainer& leftSide, const DirContainer& rightSide)
-{
- for (DirContainer::SubFileList::const_iterator i = leftSide.getSubFiles().begin(); i != leftSide.getSubFiles().end(); ++i)
- {
- const FileDescriptor& fileDescrI = i->second.getData();
- if (!fileDescrI.fileIdentifier.isNull()) //fileIdentifier may be NULL
- {
- const DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().find(i->first);
-
- //find files that exist on left and right
- if (j != rightSide.getSubFiles().end())
- {
- const FileDescriptor& fileDescrJ = j->second.getData();
- if (!fileDescrJ.fileIdentifier.isNull()) //fileIdentifier may be NULL
- {
- if ( fileDescrI.lastWriteTimeRaw == fileDescrJ.lastWriteTimeRaw &&
- fileDescrI.fileSize == fileDescrJ.fileSize)
- {
- assocDBLeftToRight_[AssocKey(fileDescrI.fileIdentifier,
- fileDescrI.lastWriteTimeRaw,
- fileDescrI.fileSize)] = fileDescrJ.fileIdentifier;
- }
- }
- }
- }
- }
-
- //-----------------------------------------------------------------------------------------------
- for (DirContainer::SubDirList::const_iterator i = leftSide.getSubDirs().begin(); i != leftSide.getSubDirs().end(); ++i)
- {
- const DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(i->first);
-
- //directories that exist on both sides
- if (j != rightSide.getSubDirs().end())
- {
- recurse(i->second, j->second); //recurse into subdirectories
- }
- }
-}
-
-
-
-class FindRenameCandidates
-{
-public:
- FindRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping)
- {
- FindDBAssoc(baseMapping,
- assocDBLeftToRight);
-
- if (!assocDBLeftToRight.empty())
- recurse(baseMapping);
- }
-
- void getRenameCandidates(std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft,
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight);
-
-private:
- void recurse(HierarchyObject& hierObj)
- {
- //files
- std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(),
- boost::bind(&FindRenameCandidates::processFile, this, _1));
-
- //directories
- std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(),
- boost::bind(&FindRenameCandidates::recurse, this, _1));//recursion
- }
-
- void processFile(FileMapping& fileObj)
- {
- switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction
- {
- case SO_CREATE_NEW_LEFT:
- if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL
- createLeft[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(),
- fileObj.getLastWriteTime<RIGHT_SIDE>(),
- fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj;
- break;
-
- case SO_CREATE_NEW_RIGHT:
- if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL
- createRight.push_back(&fileObj);
- break;
-
- case SO_DELETE_LEFT:
- if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL
- deleteLeft.push_back(&fileObj);
- break;
-
- case SO_DELETE_RIGHT:
- if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL
- deleteRight[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(),
- fileObj.getLastWriteTime<RIGHT_SIDE>(),
- fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj;
- break;
-
- case SO_OVERWRITE_RIGHT:
- case SO_OVERWRITE_LEFT:
- case SO_DO_NOTHING:
- case SO_UNRESOLVED_CONFLICT:
- break;
- }
-
- }
-
-
- std::vector<FileMapping*> createRight; //pointer always bound!
- std::vector<FileMapping*> deleteLeft; //
- // |
- // \|/
- std::map<FindDBAssoc::AssocKey, Utility::FileID> assocDBLeftToRight;
- // |
- // \|/
- std::map<FindDBAssoc::AssocKey, FileMapping*> deleteRight; //pointer always bound!
- std::map<FindDBAssoc::AssocKey, FileMapping*> createLeft; //
-
-};
-
-
-
-void FindRenameCandidates::getRenameCandidates(
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft,
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight)
-{
- for (std::vector<FileMapping*>::const_iterator crRightIter = createRight.begin();
- crRightIter != createRight.end();
- ++crRightIter)
- {
- const FindDBAssoc::AssocKey assocDbKey((*crRightIter)->getFileID<LEFT_SIDE>(),
- (*crRightIter)->getLastWriteTime<LEFT_SIDE>(),
- (*crRightIter)->getFileSize<LEFT_SIDE>());
-
- const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter =
- assocDBLeftToRight.find(assocDbKey);
-
- if (assocDBIter != assocDBLeftToRight.end())
- {
- std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator delRightIter =
- deleteRight.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side
- assocDbKey.lastWriteTimeRaw_,
- assocDbKey.fileSize_));
-
- if (delRightIter != deleteRight.end())
- {
- renameOnRight.push_back(std::make_pair(*crRightIter, delRightIter->second));
- }
- }
- }
- //------------------------------------------------------------------------------------------------
- for (std::vector<FileMapping*>::const_iterator delLeftIter = deleteLeft.begin();
- delLeftIter != deleteLeft.end();
- ++delLeftIter)
- {
- const FindDBAssoc::AssocKey assocDbKey((*delLeftIter)->getFileID<LEFT_SIDE>(),
- (*delLeftIter)->getLastWriteTime<LEFT_SIDE>(),
- (*delLeftIter)->getFileSize<LEFT_SIDE>());
-
- const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter =
- assocDBLeftToRight.find(assocDbKey);
-
- if (assocDBIter != assocDBLeftToRight.end())
- {
- std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator createLeftIter =
- createLeft.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side
- assocDbKey.lastWriteTimeRaw_,
- assocDbKey.fileSize_));
-
- if (createLeftIter != createLeft.end())
- {
- renameOnLeft.push_back(std::make_pair(createLeftIter->second, *delLeftIter));
- }
- }
- }
-}
-
-
-void FreeFileSync::getRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping, //in
- std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out
- std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight) //out throw()!
-{
- FindRenameCandidates(baseMapping).getRenameCandidates(renameOnLeft, renameOnRight);
-}
-
diff --git a/lib/detect_renaming.h b/lib/detect_renaming.h
deleted file mode 100644
index e94927c0..00000000
--- a/lib/detect_renaming.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef DETECTRENAMING_H_INCLUDED
-#define DETECTRENAMING_H_INCLUDED
-
-#include "../file_hierarchy.h"
-
-
-//identify a file "create and delete"-operation as a file renaming!
-
-namespace zen
-{
-typedef FileMapping* CreateOnLeft;
-typedef FileMapping* DeleteOnLeft;
-typedef FileMapping* CreateOnRight;
-typedef FileMapping* DeleteOnRight;
-void getRenameCandidates(zen::BaseDirMapping& baseMapping, //in
- std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out
- std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight); //out throw()!
-}
-
-#endif // DETECTRENAMING_H_INCLUDED
diff --git a/lib/dir_exist_async.h b/lib/dir_exist_async.h
index 72741ee2..f59e9490 100644
--- a/lib/dir_exist_async.h
+++ b/lib/dir_exist_async.h
@@ -20,9 +20,7 @@ bool dirExistsUpdating(const Zstring& dirname, bool allowUserInteraction, Proces
{
using namespace zen;
- std::wstring statusText = _("Searching for directory %x...");
- replace(statusText, L"%x", std::wstring(L"\"") + dirname + L"\"", false);
- procCallback.reportStatus(statusText);
+ procCallback.reportStatus(replaceCpy(_("Searching for directory %x..."), L"%x", std::wstring(L"\"") + dirname + L"\"", false));
auto ft = async([=]() -> bool
{
diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp
index 735fd7b6..ab3c84ea 100644
--- a/lib/dir_lock.cpp
+++ b/lib/dir_lock.cpp
@@ -74,10 +74,10 @@ public:
//ATTENTION: setting file pointer IS required! => use CreateFile/FILE_GENERIC_WRITE + SetFilePointerEx!
//although CreateFile/FILE_APPEND_DATA without SetFilePointerEx works locally, it MAY NOT work on some network shares creating a 4 gig file!!!
- const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_.c_str()).c_str(),
+ const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_).c_str(),
GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp
FILE_SHARE_READ,
- 0,
+ NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
@@ -340,8 +340,8 @@ std::string retrieveLockId(const Zstring& lockfilename) //throw FileError, Error
void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw FileError
{
- std::wstring infoMsg = _("Waiting while directory is locked (%x)...");
- replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + L"\"");
+ const std::wstring infoMsg = replaceCpy(_("Waiting while directory is locked (%x)..."), L"%x", std::wstring(L"\"") + lockfilename + L"\"");
+
if (callback)
callback->reportInfo(infoMsg);
//---------------------------------------------------------------
@@ -408,8 +408,8 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr
long remainingSeconds = ((DETECT_EXITUS_INTERVAL - (wxGetLocalTimeMillis() - lockSilentStart)) / 1000).ToLong();
remainingSeconds = std::max(0L, remainingSeconds);
- std::wstring remSecMsg = _P("1 sec", "%x sec", remainingSeconds);
- replace(remSecMsg, L"%x", toString<std::wstring>(remainingSeconds));
+ const std::wstring remSecMsg = replaceCpy(_P("1 sec", "%x sec", remainingSeconds), L"%x", toString<std::wstring>(remainingSeconds));
+
callback->reportInfo(infoMsg + L" " + remSecMsg);
}
else
@@ -441,7 +441,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError
const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename).c_str(),
GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0,
+ NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
@@ -472,7 +472,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError
::close(fileHandle);
#endif
- zen::ScopeGuard guardLockFile = zen::makeGuard([&]() { zen::removeFile(lockfilename); });
+ ScopeGuard guardLockFile = zen::makeGuard([&] { zen::removeFile(lockfilename); });
//write UUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks, etc.)
writeLockInfo(lockfilename); //throw FileError
diff --git a/lib/dir_name.cpp b/lib/dir_name.cpp
index 71a3e9ef..55a4185c 100644
--- a/lib/dir_name.cpp
+++ b/lib/dir_name.cpp
@@ -40,7 +40,7 @@ void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, w
if (dirPicker && !dirFormatted.empty())
{
Zstring dir = toZ(dirFormatted); //convert to Zstring first: we don't want to pass wxString by value and risk MT issues!
- auto ft = async([=]() { return zen::dirExists(dir); });
+ auto ft = async([=] { return zen::dirExists(dir); });
if (ft.timed_wait(boost::posix_time::milliseconds(timeout)) && ft.get()) //potentially slow network access: wait 200ms at most
dirPicker->SetPath(dirFormatted);
diff --git a/lib/localization.cpp b/lib/localization.cpp
index e8ff6040..574910ea 100644
--- a/lib/localization.cpp
+++ b/lib/localization.cpp
@@ -301,6 +301,7 @@ wxLanguage mapLanguageDialect(wxLanguage language)
//case wxLANGUAGE_PORTUGUESE_BRAZILIAN:
//case wxLANGUAGE_KOREAN:
//case wxLANGUAGE_UKRAINIAN:
+ //case wxLANGUAGE_CROATIAN:
//variants of wxLANGUAGE_ARABIC
case wxLANGUAGE_ARABIC_ALGERIA:
diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp
index 96b167b8..1052a408 100644
--- a/lib/parallel_scan.cpp
+++ b/lib/parallel_scan.cpp
@@ -141,7 +141,7 @@ Windows 7: Windows XP:
1 Thread: 41s | 13s 1 Thread: 45s | 13s
2 Threads: 42s | 11s 2 Threads: 38s | 8s
-=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead!
+=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead! (even faster on XP)
*/
@@ -196,7 +196,7 @@ public:
errorMsg.clear();
errorResponse.reset();
- //dummy.unlock();
+ dummy.unlock(); //optimization for condition_variable::notify_one()
conditionCanReportError.notify_one();
return rv;
@@ -204,13 +204,13 @@ public:
void processErrors(FillBufferCallback& callback) //context of main thread, call repreatedly
{
- boost::lock_guard<boost::mutex> dummy(lockErrorMsg);
+ boost::unique_lock<boost::mutex> dummy(lockErrorMsg);
if (!errorMsg.empty() && !errorResponse.get())
{
FillBufferCallback::HandleError rv = callback.reportError(copyStringTo<std::wstring>(errorMsg)); //throw!
errorResponse.reset(new FillBufferCallback::HandleError(rv));
- //dummy.unlock();
+ dummy.unlock(); //optimization for condition_variable::notify_one()
conditionGotResponse.notify_one();
}
}
@@ -293,6 +293,7 @@ private:
};
//-------------------------------------------------------------------------------------------------
+
struct TraverserShared
{
public:
@@ -372,7 +373,7 @@ void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const
Linux: retrieveFileID takes about 50% longer in VM! (avoidable because of redundant stat() call!)
*/
- output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize));
+ output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize, details.id));
cfg.acb_.incItemsScanned(); //add 1 element to the progress indicator
}
@@ -547,8 +548,8 @@ void zen::fillBuffer(const std::set<DirectoryKey>& keysToRead, //in
zen::ScopeGuard guardWorker = zen::makeGuard([&]()
{
- std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::interrupt)); //interrupt all at once, then join
- std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::join));
+ 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::shared_ptr<AsyncCallback> acb = std::make_shared<AsyncCallback>();
diff --git a/lib/status_handler.h b/lib/status_handler.h
index 390b4f0a..686c1f0e 100644
--- a/lib/status_handler.h
+++ b/lib/status_handler.h
@@ -7,7 +7,6 @@
#ifndef STATUSHANDLER_H_INCLUDED
#define STATUSHANDLER_H_INCLUDED
-#include <wx/string.h>
#include <string>
#include <zen/int64.h>
@@ -45,21 +44,18 @@ struct ProcessCallback
//note: this one must NOT throw in order to properly allow undoing setting of statistics!
//it is in general paired with a call to requestUiRefresh() to compensate!
- virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()
+ virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()!!
//opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
virtual void requestUiRefresh() = 0; //throw ?
- //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events
- virtual void forceUiRefresh() = 0;
-
//called periodically after data was processed: expected(!) to request GUI update
- virtual void reportStatus(const wxString& text) = 0; //status info only, should not be logged!
+ virtual void reportStatus(const std::wstring& text) = 0; //status info only, should not be logged!
//called periodically after data was processed: expected(!) to request GUI update
- virtual void reportInfo(const wxString& text) = 0;
+ virtual void reportInfo(const std::wstring& text) = 0;
- virtual void reportWarning(const wxString& warningMessage, bool& warningActive) = 0;
+ virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive) = 0;
//error handling:
enum Response
@@ -67,8 +63,8 @@ struct ProcessCallback
IGNORE_ERROR = 10,
RETRY
};
- virtual Response reportError (const wxString& errorMessage) = 0; //recoverable error situation
- virtual void reportFatalError(const wxString& errorMessage) = 0; //non-recoverable error situation
+ virtual Response reportError (const std::wstring& errorMessage) = 0; //recoverable error situation
+ virtual void reportFatalError(const std::wstring& errorMessage) = 0; //non-recoverable error situation
};
@@ -86,6 +82,8 @@ class StatusHandler : public ProcessCallback, public AbortCallback
public:
StatusHandler() : abortRequested(false) {}
+ virtual void forceUiRefresh() = 0;
+
virtual void requestUiRefresh()
{
if (updateUiIsAllowed()) //test if specific time span between ui updates is over
bgstack15