diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:12:46 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:12:46 +0200 |
commit | b338e29fd3eaf700f8c8360aa0310048ba941d54 (patch) | |
tree | 122f8ef3790d12cd10275ef7453a9e8053322d78 | |
parent | 3.18 (diff) | |
download | FreeFileSync-b338e29fd3eaf700f8c8360aa0310048ba941d54.tar.gz FreeFileSync-b338e29fd3eaf700f8c8360aa0310048ba941d54.tar.bz2 FreeFileSync-b338e29fd3eaf700f8c8360aa0310048ba941d54.zip |
3.19
227 files changed, 4237 insertions, 13737 deletions
diff --git a/Application.cpp b/Application.cpp index 72f5dd42..a9628646 100644 --- a/Application.cpp +++ b/Application.cpp @@ -91,7 +91,7 @@ void Application::OnStartApplication(wxIdleEvent&) try //load global settings from XML: they are written on exit, so read them FIRST { - if (fileExists(wxToZ(xmlAccess::getGlobalConfigFile()))) + if (fileExists(toZ(xmlAccess::getGlobalConfigFile()))) xmlAccess::readConfig(globalSettings); //else: globalSettings already has default values } @@ -116,11 +116,11 @@ void Application::OnStartApplication(wxIdleEvent&) { const wxString arg1(argv[1]); - if (fileExists(wxToZ(arg1))) //load file specified by %1 parameter: + if (fileExists(toZ(arg1))) //load file specified by %1 parameter: cfgFilename = arg1; - else if (fileExists(wxToZ(arg1 + wxT(".ffs_batch")))) + else if (fileExists(toZ(arg1 + wxT(".ffs_batch")))) cfgFilename = arg1 + wxT(".ffs_batch"); - else if (fileExists(wxToZ(arg1 + wxT(".ffs_gui")))) + else if (fileExists(toZ(arg1 + wxT(".ffs_gui")))) cfgFilename = arg1 + wxT(".ffs_gui"); else { @@ -242,7 +242,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet //class handling status updates and error messages BatchStatusHandler statusHandler(batchCfg.silent, zen::extractJobName(filename), - batchCfg.silent ? &batchCfg.logFileDirectory : NULL, + batchCfg.logFileDirectory, batchCfg.logFileCountMax, batchCfg.handleError, switchBatchToGui, @@ -259,8 +259,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet } //COMPARE DIRECTORIES - zen::CompareProcess comparison(batchCfg.mainCfg.handleSymlinks, - globSettings.fileTimeTolerance, + zen::CompareProcess comparison(globSettings.fileTimeTolerance, globSettings.optDialogs, statusHandler); @@ -286,7 +285,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet if (!batchCfg.silent) { const wxString soundFile = zen::getResourceDir() + wxT("Sync_Complete.wav"); - if (zen::fileExists(zen::wxToZ(soundFile))) + if (fileExists(toZ(soundFile))) wxSound::Play(soundFile, wxSOUND_ASYNC); //warning: this may fail and show a wxWidgets error message! } } diff --git a/BUILD/Changelog.txt b/BUILD/Changelog.txt index ca5e6c62..36999147 100644 --- a/BUILD/Changelog.txt +++ b/BUILD/Changelog.txt @@ -2,6 +2,28 @@ |FreeFileSync| -------------- +Changelog v3.19 +--------------- +Exclude directories from synchronization which cannot be accessed during comparison +Warning if Recycle Bin is not available instead of deleting silently +Adapted log message if missing recycler leads to permanent deletion (Windows) +Revert to per file recycle bin handling if creating temp recycler folder fails +Avoid orphaned deletion temp directories on network drives +Quick-select comparison and synchronization options via double-click +New right-click dropdown menu on comparison and synchronization settings button +New database design: copying the database file does not lead to complications anymore +Full support for "retry" while comparing +Don't copy empty folders when filtering by timespan +Allow loading/merging multiple configurations files via file open dialog +Allow loading/merging multiple configurations in last used config list +Fixed system shutdown interruption during batch mode +Allow saving log files in both silent and non-silent batch jobs +Reduced main dialog flicker when switching configurations +Database and lock files created by FreeFileSync do not trigger RealtimeSync anymore +Restrict maximum number of visible folder pairs to 6 (configurable via GlobalSettings.xml) +New macros: %day%, %hour%, %min%, %sec% + + Changelog v3.18 --------------- Launcher running synchronously and returning application error code diff --git a/BUILD/FreeFileSync.chm b/BUILD/FreeFileSync.chm Binary files differindex 66e3a195..b5c6039c 100644 --- a/BUILD/FreeFileSync.chm +++ b/BUILD/FreeFileSync.chm diff --git a/BUILD/Help/html/advanced/Macros.html b/BUILD/Help/html/advanced/Macros.html index b8126555..a513f458 100644 --- a/BUILD/Help/html/advanced/Macros.html +++ b/BUILD/Help/html/advanced/Macros.html @@ -5,7 +5,7 @@ <TITLE></TITLE> <META NAME="GENERATOR" CONTENT="OpenOffice.org 3.2 (Win32)"> <META NAME="CREATED" CONTENT="20091206;16574000"> - <META NAME="CHANGED" CONTENT="20110417;18595700"> + <META NAME="CHANGED" CONTENT="20110718;14131000"> <META NAME="Info 1" CONTENT=""> <META NAME="Info 2" CONTENT=""> <META NAME="Info 3" CONTENT=""> @@ -39,12 +39,16 @@ macros:</B></FONT></P> <P><SPAN ID="Rahmen4" DIR="LTR" STYLE="float: left; width: 80%; height: 0.14cm; border: none; padding: 0cm; background: #e6e6e6"> <UL> <P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><FONT FACE="Courier New, monospace">%time% - - </FONT>current time, format [hhmmss], e. g. "<FONT FACE="Courier New, monospace">201340</FONT>"<BR><FONT FACE="Courier New, monospace">%weekday% - - </FONT>day of the week, e. g. "<FONT FACE="Courier New, monospace">Monday</FONT>"<BR><FONT FACE="Courier New, monospace">%date% - - </FONT>current date, e. g. "<FONT FACE="Courier New, monospace">2010-07-13</FONT>"<BR><FONT FACE="Courier New, monospace">%week% - - </FONT>calendar week, e. g. "<FONT FACE="Courier New, monospace">28</FONT>"<BR><FONT FACE="Courier New, monospace">%month% - + </FONT>current time, format [hhmmss], e. g. "<FONT FACE="Courier New, monospace">201340</FONT>"<BR><FONT FACE="Courier New, monospace">%date% - + </FONT>current date, e. g. "<FONT FACE="Courier New, monospace">2010-07-13</FONT>"<BR><BR><FONT FACE="Courier New, monospace">%weekday% - + </FONT>day of the week, e. g. "<FONT FACE="Courier New, monospace">Monday</FONT>"<BR><FONT FACE="Courier New, monospace">%week% - + </FONT>calendar week, e. g. "<FONT FACE="Courier New, monospace">28</FONT>"<BR><BR><FONT FACE="Courier New, monospace">%day% - + </FONT>current day, e. g. "<FONT FACE="Courier New, monospace">21</FONT>"<BR><FONT FACE="Courier New, monospace">%month% - </FONT>current month, e. g. "<FONT FACE="Courier New, monospace">July</FONT>"<BR><FONT FACE="Courier New, monospace">%year% - - </FONT>current year, e. g. "<FONT FACE="Courier New, monospace">2010</FONT>"</FONT></P> + </FONT>current year, e. g. "<FONT FACE="Courier New, monospace">2010</FONT>"<BR><BR><FONT FACE="Courier New, monospace">%hour% - + </FONT>current hour, e. g. "<FONT FACE="Courier New, monospace">20</FONT>"<BR><FONT FACE="Courier New, monospace">%min% - + </FONT>current minute, e. g. "<FONT FACE="Courier New, monospace">13</FONT>"<BR><FONT FACE="Courier New, monospace">%sec% - + </FONT>current second, e. g. "<FONT FACE="Courier New, monospace">40</FONT>"</FONT></P> </UL> </SPAN><BR CLEAR=LEFT> </P> @@ -65,7 +69,6 @@ add a great amount of flexibility to Batch Synchronization <LI><P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"> <FONT FACE="Tahoma, sans-serif"><FONT FACE="Courier New, monospace">C:\Backup\%username%_Config </FONT>expands to<FONT FACE="Courier New, monospace"><BR>C:\Backup\ZenJu_Config</FONT></FONT></P> - <P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"></P> <LI><P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"> <FONT FACE="Tahoma, sans-serif"><FONT FACE="Courier New, monospace">%appdata%\FreeFileSync </FONT>expands to<FONT FACE="Courier New, monospace"><BR>C:\Documents and diff --git a/BUILD/Languages/german.lng b/BUILD/Languages/german.lng index fa8031f9..b9e4ffe2 100644 --- a/BUILD/Languages/german.lng +++ b/BUILD/Languages/german.lng @@ -109,10 +109,10 @@ <target>Erstmalige Synchronisation:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Eine der FreeFileSync Datenbankdateien existiert noch nicht:</target> -<source>One of the FreeFileSync database entries within the following file is not yet existing:</source> -<target>Einer der FreeFileSync Datenbankeinträge innerhalb der folgenden Datei existiert noch nicht:</target> <source>Error reading from synchronization database:</source> <target>Fehler beim Lesen der Synchronisationsdatenbank:</target> +<source>No matching synchronization session found in database files:</source> +<target></target> <source>An exception occurred!</source> <target>Eine Ausnahme ist aufgetreten!</target> <source>Error deleting file:</source> @@ -134,7 +134,7 @@ <source>Info</source> <target>Info</target> <source>Fatal Error</source> -<target>Fataler Fehler</target> +<target>Schwerer Fehler</target> <source>Invalid FreeFileSync config file!</source> <target>Ungültige FreeFileSync Konfigurationsdatei!</target> <source>File does not exist:</source> @@ -695,10 +695,6 @@ Transfer file and directory permissions <target>Verzeichnispaare</target> <source>Select view</source> <target>Ansicht auswählen</target> -<source>Folder Comparison and Synchronization</source> -<target>Verzeichnisvergleich und Synchronisation</target> -<source>Recycle Bin not yet supported for this system!</source> -<target>Der Papierkorb wird für dieses System noch nicht unterstützt!</target> <source>Set direction:</source> <target>Setze Richtung:</target> <source>Exclude temporarily</source> @@ -733,6 +729,8 @@ Transfer file and directory permissions <target>Änderungen der aktuellen Konfiguration sichern?</target> <source>Configuration loaded!</source> <target>Konfiguration geladen!</target> +<source>Folder Comparison and Synchronization</source> +<target>Verzeichnisvergleich und Synchronisation</target> <source>Hide files that exist on left side only</source> <target>Nur links existierende Dateien ausblenden</target> <source>Show files that exist on left side only</source> @@ -1043,6 +1041,8 @@ Transfer file and directory permissions <target>Benötigter freier Speicherplatz:</target> <source>Free disk space available:</source> <target>Verfügbarer freier Speicherplatz:</target> +<source>Recycle Bin is not available for the following paths! Files will be deleted permanently instead:</source> +<target></target> <source>A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!</source> <target>Es wird ein Verzeichnis verändert werden, das Teil mehrerer Verzeichnispaare ist! Bitte die Synchronisationseinstellungen prüfen!</target> <source>Processing folder pair:</source> diff --git a/BUILD/Resources.dat b/BUILD/Resources.dat Binary files differindex 6af47f50..a88b0703 100644 --- a/BUILD/Resources.dat +++ b/BUILD/Resources.dat diff --git a/FreeFileSync - wxWidgets v2.9.1 Beta.vcxproj b/FreeFileSync - wxWidgets v2.9.2 Beta.vcxproj index e9157291..5a878c54 100644 --- a/FreeFileSync - wxWidgets v2.9.1 Beta.vcxproj +++ b/FreeFileSync - wxWidgets v2.9.2 Beta.vcxproj @@ -101,7 +101,7 @@ <WarningLevel>Level4</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <PrecompiledHeaderFile>$(ProjectDir)shared\pch.h</PrecompiledHeaderFile> <DisableSpecificWarnings>4996;4100;</DisableSpecificWarnings> <MultiProcessorCompilation>false</MultiProcessorCompilation> @@ -117,12 +117,12 @@ <SuppressStartupBanner>true</SuppressStartupBanner> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <AdditionalDependencies>wxmsw29ud_aui.lib;wxmsw29ud_adv.lib;wxmsw29ud_core.lib;wxbase29ud.lib;wxpngd.lib;wxzlibd.lib;wxbase29ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> - <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> </Link> <ResourceCompile> - <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswud</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswud</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> </ResourceCompile> <Manifest> @@ -157,7 +157,7 @@ </LinkStatus> </Link> <ResourceCompile> - <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswud</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswud</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> </ResourceCompile> <Manifest> @@ -173,7 +173,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> <DisableSpecificWarnings>4996;4100;</DisableSpecificWarnings> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> @@ -189,12 +189,12 @@ <SuppressStartupBanner>true</SuppressStartupBanner> <AdditionalDependencies>wxmsw29u_aui.lib;wxmsw29u_adv.lib;wxmsw29u_core.lib;wxbase29u.lib;wxpng.lib;wxzlib.lib;wxbase29u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> </Link> <ResourceCompile> - <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswu</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswu</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> <Culture> </Culture> @@ -210,7 +210,7 @@ <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <DisableSpecificWarnings>4996;4100;</DisableSpecificWarnings> + <DisableSpecificWarnings>4512;4996;4100;4127</DisableSpecificWarnings> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <MultiProcessorCompilation>true</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> @@ -230,7 +230,7 @@ </LinkStatus> </Link> <ResourceCompile> - <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.1\include;C:\Program Files\C++\wxWidgets-2.9.1\lib\vc_lib\mswu</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-2.9.2\include;C:\Program Files\C++\wxWidgets-2.9.2\lib\vc_lib\mswu</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> <Culture> </Culture> @@ -267,7 +267,6 @@ <ClCompile Include="shared\file_id.cpp" /> <ClCompile Include="shared\file_io.cpp" /> <ClCompile Include="shared\file_traverser.cpp" /> - <ClCompile Include="shared\global_func.cpp" /> <ClCompile Include="shared\guid.cpp" /> <ClCompile Include="shared\help_provider.cpp" /> <ClCompile Include="shared\i18n.cpp" /> diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp index 19170659..53917e8d 100644 --- a/FreeFileSync.cbp +++ b/FreeFileSync.cbp @@ -29,7 +29,7 @@ <Add library="libwxpng.a" /> <Add library="libwxzlib.a" /> <Add library="libwxbase28u_net.a" /> - <Add library="libboost_thread-mgw45-mt-s-1_46_1.a" /> + <Add library="libboost_thread-mgw45-mt-s-1_47.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" /> </Linker> </Target> @@ -55,7 +55,7 @@ <Add library="libwxbase28ud.a" /> <Add library="libwxpngd.a" /> <Add library="libwxzlibd.a" /> - <Add library="libboost_thread-mgw45-mt-sd-1_46_1.a" /> + <Add library="libboost_thread-mgw45-mt-sd-1_47.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_dll" /> </Linker> </Target> @@ -79,7 +79,7 @@ <Add library="libwxbase28ud.a" /> <Add library="libwxbase28ud_net.a" /> <Add library="libwxmsw28ud_aui.a" /> - <Add library="libboost_thread-mgw45-mt-sd-1_46_1.a" /> + <Add library="libboost_thread-mgw45-mt-sd-1_47.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_dll" /> </Linker> </Target> @@ -277,7 +277,6 @@ <Unit filename="shared\file_io.h" /> <Unit filename="shared\file_traverser.cpp" /> <Unit filename="shared\file_traverser.h" /> - <Unit filename="shared\global_func.cpp" /> <Unit filename="shared\global_func.h" /> <Unit filename="shared\guid.cpp" /> <Unit filename="shared\guid.h" /> @@ -350,6 +349,7 @@ <Unit filename="shared\zbase.h" /> <Unit filename="shared\zstring.cpp" /> <Unit filename="shared\zstring.h" /> + <Unit filename="shared\zxstring.h" /> <Unit filename="structures.cpp" /> <Unit filename="structures.h"> <Option target="<{~None~}>" /> diff --git a/FreeFileSync.vcxproj b/FreeFileSync.vcxproj index 7c38c5a0..f2025456 100644 --- a/FreeFileSync.vcxproj +++ b/FreeFileSync.vcxproj @@ -1 +1,319 @@ -<?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>{86C36CC7-9418-4253-9928-828486F59A00}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>FreeFileSync</RootNamespace> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> <PlatformToolset>v100</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> <PlatformToolset>Windows7.1SDK</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> <PlatformToolset>v100</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> <PlatformToolset>Windows7.1SDK</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <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> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <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> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>BUILD\Bin\</OutDir> <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> <TargetName>$(ProjectName)_$(PlatformName)</TargetName> <GenerateManifest>false</GenerateManifest> <EmbedManifest>true</EmbedManifest> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <LinkIncremental>true</LinkIncremental> <OutDir>BUILD\Bin\</OutDir> <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> <TargetName>$(ProjectName)_$(PlatformName)</TargetName> <GenerateManifest>false</GenerateManifest> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <LinkIncremental>false</LinkIncremental> <OutDir>BUILD\Bin\</OutDir> <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> <GenerateManifest>false</GenerateManifest> <TargetName>$(ProjectName)_$(PlatformName)</TargetName> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <LinkIncremental>false</LinkIncremental> <OutDir>BUILD\Bin\</OutDir> <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> <GenerateManifest>false</GenerateManifest> <TargetName>$(ProjectName)_$(PlatformName)</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader>Use</PrecompiledHeader> <WarningLevel>Level4</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <PrecompiledHeaderFile>$(ProjectDir)shared\pch.h</PrecompiledHeaderFile> <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> <MultiProcessorCompilation>false</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> <PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile> <ForcedIncludeFiles>$(ProjectDir)shared/pch.h</ForcedIncludeFiles> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <SuppressStartupBanner>true</SuppressStartupBanner> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <AdditionalDependencies>wxmsw28ud_aui.lib;wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> </Link> <ResourceCompile> <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> </ResourceCompile> <Manifest> <SuppressDependencyElement> </SuppressDependencyElement> </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <PrecompiledHeader>Use</PrecompiledHeader> <WarningLevel>Level4</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <PrecompiledHeaderFile>$(ProjectDir)shared\pch.h</PrecompiledHeaderFile> <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> <MultiProcessorCompilation>false</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> <PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile> <ForcedIncludeFiles>$(ProjectDir)shared/pch.h</ForcedIncludeFiles> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <SuppressStartupBanner>true</SuppressStartupBanner> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <SuppressStartupBanner>true</SuppressStartupBanner> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <AdditionalDependencies>wxmsw28ud_aui.lib;wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> </Link> <ResourceCompile> <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> </ResourceCompile> <Manifest> <SuppressDependencyElement> </SuppressDependencyElement> </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level4</WarningLevel> <PrecompiledHeader>NotUsing</PrecompiledHeader> <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <MultiProcessorCompilation>true</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> <InlineFunctionExpansion>Default</InlineFunctionExpansion> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> <SuppressStartupBanner>true</SuppressStartupBanner> <AdditionalDependencies>wxmsw28u_aui.lib;wxmsw28u_adv.lib;wxmsw28u_core.lib;wxbase28u.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> </Link> <ResourceCompile> <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> <Culture> </Culture> </ResourceCompile> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <WarningLevel>Level4</WarningLevel> <PrecompiledHeader>NotUsing</PrecompiledHeader> <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <MultiProcessorCompilation>true</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> <SuppressStartupBanner>true</SuppressStartupBanner> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> <SuppressStartupBanner>true</SuppressStartupBanner> <AdditionalDependencies>wxmsw28u_aui.lib;wxmsw28u_adv.lib;wxmsw28u_core.lib;wxbase28u.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories> <LinkStatus> </LinkStatus> <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> </Link> <ResourceCompile> <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> <Culture> </Culture> </ResourceCompile> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="algorithm.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> </ClCompile> <ClCompile Include="application.cpp" /> <ClCompile Include="comparison.cpp" /> <ClCompile Include="file_hierarchy.cpp" /> <ClCompile Include="library\binary.cpp" /> <ClCompile Include="library\custom_grid.cpp" /> <ClCompile Include="library\db_file.cpp" /> <ClCompile Include="library\dir_lock.cpp" /> <ClCompile Include="library\error_log.cpp" /> <ClCompile Include="library\hard_filter.cpp" /> <ClCompile Include="library\icon_buffer.cpp" /> <ClCompile Include="library\process_xml.cpp" /> <ClCompile Include="library\resources.cpp" /> <ClCompile Include="library\statistics.cpp" /> <ClCompile Include="library\status_handler.cpp" /> <ClCompile Include="shared\app_main.cpp" /> <ClCompile Include="shared\check_exist.cpp" /> <ClCompile Include="shared\custom_button.cpp" /> <ClCompile Include="shared\custom_combo_box.cpp" /> <ClCompile Include="shared\custom_tooltip.cpp" /> <ClCompile Include="shared\dll_loader.cpp" /> <ClCompile Include="shared\dir_name.cpp" /> <ClCompile Include="shared\dst_hack.cpp" /> <ClCompile Include="shared\file_handling.cpp" /> <ClCompile Include="shared\file_id.cpp" /> <ClCompile Include="shared\file_io.cpp" /> <ClCompile Include="shared\file_traverser.cpp" /> <ClCompile Include="shared\global_func.cpp" /> <ClCompile Include="shared\guid.cpp" /> <ClCompile Include="shared\help_provider.cpp" /> <ClCompile Include="shared\i18n.cpp" /> <ClCompile Include="shared\localization.cpp" /> <ClCompile Include="shared\mouse_move_dlg.cpp" /> <ClCompile Include="shared\privilege.cpp" /> <ClCompile Include="shared\recycler.cpp" /> <ClCompile Include="shared\resolve_path.cpp" /> <ClCompile Include="shared\serialize.cpp" /> <ClCompile Include="shared\shadow.cpp" /> <ClCompile Include="shared\standard_paths.cpp" /> <ClCompile Include="shared\last_error.cpp" /> <ClCompile Include="shared\taskbar.cpp" /> <ClCompile Include="shared\toggle_button.cpp" /> <ClCompile Include="shared\util.cpp" /> <ClCompile Include="shared\xml_base.cpp" /> <ClCompile Include="shared\zenXml\unit_test.cpp" /> <ClCompile Include="shared\zstring.cpp" /> <ClCompile Include="structures.cpp" /> <ClCompile Include="synchronization.cpp" /> <ClCompile Include="ui\batch_config.cpp" /> <ClCompile Include="ui\batch_status_handler.cpp" /> <ClCompile Include="ui\check_version.cpp" /> <ClCompile Include="ui\grid_view.cpp" /> <ClCompile Include="ui\gui_generated.cpp" /> <ClCompile Include="ui\gui_status_handler.cpp" /> <ClCompile Include="ui\main_dlg.cpp" /> <ClCompile Include="ui\msg_popup.cpp" /> <ClCompile Include="ui\progress_indicator.cpp" /> <ClCompile Include="ui\search.cpp" /> <ClCompile Include="ui\small_dlgs.cpp" /> <ClCompile Include="ui\switch_to_gui.cpp" /> <ClCompile Include="ui\sync_cfg.cpp" /> <ClCompile Include="ui\tray_icon.cpp" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="resource.rc" /> </ItemGroup> <ItemGroup> <None Include="WxWizFrame.fbp"> <SubType>Designer</SubType> </None> </ItemGroup> <ItemGroup> <ClInclude Include="shared\pch.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup></Project>
\ No newline at end of file +<?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>{86C36CC7-9418-4253-9928-828486F59A00}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>FreeFileSync</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v100</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v100</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>Windows7.1SDK</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <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> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <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> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>BUILD\Bin\</OutDir> + <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> + <TargetName>$(ProjectName)_$(PlatformName)</TargetName> + <GenerateManifest>false</GenerateManifest> + <EmbedManifest>true</EmbedManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>BUILD\Bin\</OutDir> + <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> + <TargetName>$(ProjectName)_$(PlatformName)</TargetName> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>BUILD\Bin\</OutDir> + <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> + <GenerateManifest>false</GenerateManifest> + <TargetName>$(ProjectName)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>BUILD\Bin\</OutDir> + <IntDir>OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir> + <GenerateManifest>false</GenerateManifest> + <TargetName>$(ProjectName)_$(PlatformName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <PrecompiledHeaderFile>$(ProjectDir)shared\pch.h</PrecompiledHeaderFile> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <MultiProcessorCompilation>false</MultiProcessorCompilation> + <DisableLanguageExtensions>false</DisableLanguageExtensions> + <PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile> + <ForcedIncludeFiles>$(ProjectDir)shared/pch.h</ForcedIncludeFiles> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalDependencies>wxmsw28ud_aui.lib;wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> + <LinkStatus> + </LinkStatus> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> + </ResourceCompile> + <Manifest> + <SuppressDependencyElement> + </SuppressDependencyElement> + </Manifest> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <PrecompiledHeaderFile>$(ProjectDir)shared\pch.h</PrecompiledHeaderFile> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <MultiProcessorCompilation>false</MultiProcessorCompilation> + <DisableLanguageExtensions>false</DisableLanguageExtensions> + <PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile> + <ForcedIncludeFiles>$(ProjectDir)shared/pch.h</ForcedIncludeFiles> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalDependencies>wxmsw28ud_aui.lib;wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories> + <LinkStatus> + </LinkStatus> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswud</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> + </ResourceCompile> + <Manifest> + <SuppressDependencyElement> + </SuppressDependencyElement> + </Manifest> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level4</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DisableLanguageExtensions>false</DisableLanguageExtensions> + <InlineFunctionExpansion>Default</InlineFunctionExpansion> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <SuppressStartupBanner>true</SuppressStartupBanner> + <AdditionalDependencies>wxmsw28u_aui.lib;wxmsw28u_adv.lib;wxmsw28u_core.lib;wxbase28u.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories> + <LinkStatus> + </LinkStatus> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions> + <Culture> + </Culture> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level4</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>.\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <DisableSpecificWarnings>4512;4996;4100;4127</DisableSpecificWarnings> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DisableLanguageExtensions>false</DisableLanguageExtensions> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <SuppressStartupBanner>true</SuppressStartupBanner> + <AdditionalDependencies>wxmsw28u_aui.lib;wxmsw28u_adv.lib;wxmsw28u_core.lib;wxbase28u.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories> + <LinkStatus> + </LinkStatus> + <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions> + <Culture> + </Culture> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="algorithm.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="application.cpp" /> + <ClCompile Include="comparison.cpp" /> + <ClCompile Include="file_hierarchy.cpp" /> + <ClCompile Include="library\binary.cpp" /> + <ClCompile Include="library\custom_grid.cpp" /> + <ClCompile Include="library\db_file.cpp" /> + <ClCompile Include="library\dir_lock.cpp" /> + <ClCompile Include="library\error_log.cpp" /> + <ClCompile Include="library\hard_filter.cpp" /> + <ClCompile Include="library\icon_buffer.cpp" /> + <ClCompile Include="library\process_xml.cpp" /> + <ClCompile Include="library\resources.cpp" /> + <ClCompile Include="library\statistics.cpp" /> + <ClCompile Include="library\status_handler.cpp" /> + <ClCompile Include="shared\app_main.cpp" /> + <ClCompile Include="shared\check_exist.cpp" /> + <ClCompile Include="shared\custom_button.cpp" /> + <ClCompile Include="shared\custom_combo_box.cpp" /> + <ClCompile Include="shared\custom_tooltip.cpp" /> + <ClCompile Include="shared\dll_loader.cpp" /> + <ClCompile Include="shared\dir_name.cpp" /> + <ClCompile Include="shared\dst_hack.cpp" /> + <ClCompile Include="shared\file_handling.cpp" /> + <ClCompile Include="shared\file_id.cpp" /> + <ClCompile Include="shared\file_io.cpp" /> + <ClCompile Include="shared\file_traverser.cpp" /> + <ClCompile Include="shared\guid.cpp" /> + <ClCompile Include="shared\help_provider.cpp" /> + <ClCompile Include="shared\i18n.cpp" /> + <ClCompile Include="shared\localization.cpp" /> + <ClCompile Include="shared\mouse_move_dlg.cpp" /> + <ClCompile Include="shared\privilege.cpp" /> + <ClCompile Include="shared\recycler.cpp" /> + <ClCompile Include="shared\resolve_path.cpp" /> + <ClCompile Include="shared\serialize.cpp" /> + <ClCompile Include="shared\shadow.cpp" /> + <ClCompile Include="shared\standard_paths.cpp" /> + <ClCompile Include="shared\last_error.cpp" /> + <ClCompile Include="shared\taskbar.cpp" /> + <ClCompile Include="shared\toggle_button.cpp" /> + <ClCompile Include="shared\util.cpp" /> + <ClCompile Include="shared\xml_base.cpp" /> + <ClCompile Include="shared\zenXml\unit_test.cpp" /> + <ClCompile Include="shared\zstring.cpp" /> + <ClCompile Include="structures.cpp" /> + <ClCompile Include="synchronization.cpp" /> + <ClCompile Include="ui\batch_config.cpp" /> + <ClCompile Include="ui\batch_status_handler.cpp" /> + <ClCompile Include="ui\check_version.cpp" /> + <ClCompile Include="ui\grid_view.cpp" /> + <ClCompile Include="ui\gui_generated.cpp" /> + <ClCompile Include="ui\gui_status_handler.cpp" /> + <ClCompile Include="ui\main_dlg.cpp" /> + <ClCompile Include="ui\msg_popup.cpp" /> + <ClCompile Include="ui\progress_indicator.cpp" /> + <ClCompile Include="ui\search.cpp" /> + <ClCompile Include="ui\small_dlgs.cpp" /> + <ClCompile Include="ui\switch_to_gui.cpp" /> + <ClCompile Include="ui\sync_cfg.cpp" /> + <ClCompile Include="ui\tray_icon.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="resource.rc" /> + </ItemGroup> + <ItemGroup> + <None Include="WxWizFrame.fbp"> + <SubType>Designer</SubType> + </None> + </ItemGroup> + <ItemGroup> + <ClInclude Include="shared\pch.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file @@ -69,7 +69,6 @@ FILE_LIST+=shared/dir_name.cpp FILE_LIST+=shared/guid.cpp FILE_LIST+=shared/xml_base.cpp FILE_LIST+=shared/check_exist.cpp -FILE_LIST+=shared/global_func.cpp FILE_LIST+=shared/last_error.cpp FILE_LIST+=shared/custom_tooltip.cpp FILE_LIST+=shared/file_handling.cpp diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp index 9e81c8ea..867b898c 100644 --- a/RealtimeSync/RealtimeSync.cbp +++ b/RealtimeSync/RealtimeSync.cbp @@ -27,7 +27,7 @@ <Add library="libwxbase28u.a" /> <Add library="libwxpng.a" /> <Add library="libwxzlib.a" /> - <Add library="libboost_thread-mgw45-mt-s-1_46_1.a" /> + <Add library="libboost_thread-mgw45-mt-s-1_47.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" /> </Linker> </Target> @@ -51,7 +51,7 @@ <Add library="libwxbase28ud.a" /> <Add library="libwxpngd.a" /> <Add library="libwxzlibd.a" /> - <Add library="libboost_thread-mgw45-mt-sd-1_46_1.a" /> + <Add library="libboost_thread-mgw45-mt-sd-1_47.a" /> <Add directory="C:\Program Files\C++\wxWidgets\lib\gcc_dll" /> </Linker> </Target> @@ -101,7 +101,6 @@ <Unit filename="gui_generated.h" /> <Unit filename="main_dlg.cpp" /> <Unit filename="main_dlg.h" /> - <Unit filename="notify.cpp" /> <Unit filename="notify.h" /> <Unit filename="resource.rc"> <Option compilerVar="WINDRES" /> @@ -124,6 +123,8 @@ <Unit filename="..\Shared\zstring.h" /> <Unit filename="..\library\process_xml.cpp" /> <Unit filename="..\shared\check_exist.cpp" /> + <Unit filename="..\shared\dir_watcher.cpp" /> + <Unit filename="..\shared\dir_watcher.h" /> <Unit filename="..\shared\dll_loader.cpp" /> <Unit filename="..\shared\dll_loader.h" /> <Unit filename="..\shared\dst_hack.cpp" /> @@ -134,7 +135,6 @@ <Unit filename="..\shared\file_id.cpp" /> <Unit filename="..\shared\file_io.cpp" /> <Unit filename="..\shared\file_traverser.cpp" /> - <Unit filename="..\shared\global_func.cpp" /> <Unit filename="..\shared\global_func.h" /> <Unit filename="..\shared\help_provider.cpp" /> <Unit filename="..\shared\i18n.cpp" /> @@ -144,6 +144,8 @@ <Unit filename="..\shared\localization.cpp" /> <Unit filename="..\shared\long_path_prefix.h" /> <Unit filename="..\shared\mouse_move_dlg.cpp" /> + <Unit filename="..\shared\notify_removal.cpp" /> + <Unit filename="..\shared\notify_removal.h" /> <Unit filename="..\shared\pch.h"> <Option compile="1" /> <Option weight="0" /> diff --git a/RealtimeSync/RealtimeSync.vcxproj b/RealtimeSync/RealtimeSync.vcxproj index 12d36822..cdeb18b4 100644 --- a/RealtimeSync/RealtimeSync.vcxproj +++ b/RealtimeSync/RealtimeSync.vcxproj @@ -199,7 +199,7 @@ <PreprocessorDefinitions>ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>..\shared;C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> + <DisableSpecificWarnings>4512;4996;4100;4127</DisableSpecificWarnings> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <MultiProcessorCompilation>true</MultiProcessorCompilation> <DisableLanguageExtensions>false</DisableLanguageExtensions> @@ -228,17 +228,18 @@ <ClCompile Include="..\library\process_xml.cpp" /> <ClCompile Include="..\shared\check_exist.cpp" /> <ClCompile Include="..\shared\custom_button.cpp" /> + <ClCompile Include="..\shared\dir_watcher.cpp" /> <ClCompile Include="..\shared\dll_loader.cpp" /> <ClCompile Include="..\shared\dir_name.cpp" /> <ClCompile Include="..\shared\dst_hack.cpp" /> <ClCompile Include="..\shared\file_handling.cpp" /> <ClCompile Include="..\shared\file_io.cpp" /> <ClCompile Include="..\shared\file_traverser.cpp" /> - <ClCompile Include="..\shared\global_func.cpp" /> <ClCompile Include="..\shared\help_provider.cpp" /> <ClCompile Include="..\shared\i18n.cpp" /> <ClCompile Include="..\shared\localization.cpp" /> <ClCompile Include="..\shared\mouse_move_dlg.cpp" /> + <ClCompile Include="..\shared\notify_removal.cpp" /> <ClCompile Include="..\shared\privilege.cpp" /> <ClCompile Include="..\shared\resolve_path.cpp" /> <ClCompile Include="..\shared\standard_paths.cpp" /> @@ -254,7 +255,6 @@ </ClCompile> <ClCompile Include="gui_generated.cpp" /> <ClCompile Include="main_dlg.cpp" /> - <ClCompile Include="notify.cpp" /> <ClCompile Include="resources.cpp" /> <ClCompile Include="tray_menu.cpp" /> <ClCompile Include="watcher.cpp" /> diff --git a/RealtimeSync/application.cpp b/RealtimeSync/application.cpp index 75f77da4..196e0ecc 100644 --- a/RealtimeSync/application.cpp +++ b/RealtimeSync/application.cpp @@ -42,7 +42,7 @@ void Application::OnStartApplication(wxIdleEvent& event) SetAppName(wxT("FreeFileSync")); //use a different app name, to have "GetUserDataDir()" return the same directory as for FreeFileSync #ifdef FFS_LINUX - ::gtk_rc_parse((zen::wxToZ(zen::getResourceDir()) + "styles.rc").c_str()); //remove inner border from bitmap buttons + ::gtk_rc_parse((zen::utf8CvrtTo<std::string>(zen::getResourceDir()) + "styles.rc").c_str()); //remove inner border from bitmap buttons #endif //set program language diff --git a/RealtimeSync/main_dlg.cpp b/RealtimeSync/main_dlg.cpp index 5a89e4cd..860ddcef 100644 --- a/RealtimeSync/main_dlg.cpp +++ b/RealtimeSync/main_dlg.cpp @@ -16,7 +16,6 @@ #include "tray_menu.h" #include "../shared/file_handling.h" #include "xml_ffs.h" -#include "../shared/system_constants.h" #include "../shared/string_conv.h" #include "../shared/assert_static.h" #include "../shared/build_info.h" diff --git a/RealtimeSync/makefile b/RealtimeSync/makefile index 56e8eb60..2e123af2 100644 --- a/RealtimeSync/makefile +++ b/RealtimeSync/makefile @@ -30,8 +30,7 @@ FILE_LIST+=../shared/util.cpp FILE_LIST+=../shared/check_exist.cpp FILE_LIST+=../shared/i18n.cpp FILE_LIST+=../shared/localization.cpp -FILE_LIST+=../shared/inotify/inotify-cxx.cpp -FILE_LIST+=../shared/global_func.cpp +FILE_LIST+=../shared/dir_watcher.cpp FILE_LIST+=../shared/last_error.cpp FILE_LIST+=../shared/dir_name.cpp FILE_LIST+=../shared/zstring.cpp diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp index 24356ff8..3f7f7988 100644 --- a/RealtimeSync/resources.cpp +++ b/RealtimeSync/resources.cpp @@ -11,7 +11,6 @@ #include <wx/icon.h> #include <memory> #include "../shared/standard_paths.h" -#include "../shared/system_constants.h" using namespace zen; diff --git a/RealtimeSync/tray_menu.cpp b/RealtimeSync/tray_menu.cpp index d42aea0a..e6d5f0d4 100644 --- a/RealtimeSync/tray_menu.cpp +++ b/RealtimeSync/tray_menu.cpp @@ -27,7 +27,7 @@ #include "../shared/shell_execute.h" using namespace rts; - +using namespace zen; class TrayIconHolder : private wxEvtHandler { @@ -227,7 +227,7 @@ std::vector<Zstring> convert(const std::vector<wxString>& dirList) { std::set<Zstring, LessFilename> output; std::transform(dirList.begin(), dirList.end(), - std::inserter(output, output.end()), static_cast<Zstring (*)(const wxString&)>(zen::wxToZ)); + std::inserter(output, output.end()), [](const wxString& str) { return zen::toZ(str); }); return std::vector<Zstring>(output.begin(), output.end()); } } @@ -299,9 +299,9 @@ rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& if (config.commandline.empty()) { - wxString errorMsg = _("Invalid commandline: \"%x\""); - errorMsg.Replace(L"%x", config.commandline); - throw zen::FileError(errorMsg); + std::wstring errorMsg = _("Invalid commandline: \"%x\""); + replace(errorMsg, L"%x", config.commandline); + throw FileError(errorMsg); } callback.notifyDirectoryMissing(); @@ -337,7 +337,7 @@ rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& callback.scheduleNextSync(wxGetLocalTime() + static_cast<long>(config.delay)); } } - catch (StartSyncNowException) {} + catch (StartSyncNowException&) {} } } catch (const ::AbortThisProcess& ab) diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp index 7cd062b7..059f420b 100644 --- a/RealtimeSync/watcher.cpp +++ b/RealtimeSync/watcher.cpp @@ -5,28 +5,16 @@ // ************************************************************************** // #include "watcher.h" -#include "../shared/last_error.h" -#include "../shared/string_conv.h" #include "../shared/file_handling.h" #include "../shared/i18n.h" -#include <stdexcept> #include <set> #include <wx/timer.h> -#include <algorithm> #include "../shared/resolve_path.h" - -#ifdef FFS_WIN -#include "notify.h" -#include <wx/msw/wrapwin.h> //includes "windows.h" -#include "../shared/long_path_prefix.h" -#include <boost/shared_ptr.hpp> -#include "../shared/loki/ScopeGuard.h" -#include <boost/scoped_array.hpp> - -#elif defined FFS_LINUX -#include "../shared/inotify/inotify-cxx.h" -#include "../shared/file_traverser.h" -#endif +#include "../shared/dir_watcher.h" +#include "../shared/string_conv.h" +//#include "../library/db_file.h" //SYNC_DB_FILE_ENDING -> complete file too much of a dependency; file ending too little to decouple into single header +//#include "../library/lock_holder.h" //LOCK_FILE_ENDING +#include <wx/msgdlg.h> using namespace zen; @@ -45,45 +33,10 @@ bool rts::updateUiIsAllowed() } -#ifdef FFS_WIN -//shared_ptr custom deleter -void cleanUpChangeNotifications(const std::vector<HANDLE>* handles) -{ - for (std::vector<HANDLE>::const_iterator i = handles->begin(); i != handles->end(); ++i) - if (*i != INVALID_HANDLE_VALUE) - ::FindCloseChangeNotification(*i); - - delete handles; //don't forget!!! custom deleter needs to care for everything! -} - -#elif defined FFS_LINUX -class DirsOnlyTraverser : public zen::TraverseCallback +class MonitorExistence //detect changes to directory availability { public: - DirsOnlyTraverser(std::vector<std::string>& dirs) : m_dirs(dirs) {} - - virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) {} - virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) - { - m_dirs.push_back(fullName.c_str()); - return ReturnValDir(Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_CONTINUE>(), *this); - } - virtual void onError(const wxString& errorText) - { - throw zen::FileError(errorText); - } - -private: - std::vector<std::string>& m_dirs; -}; -#endif - - -class WatchDirectories //detect changes to directory availability -{ -public: - WatchDirectories() : allExisting_(true) {} + MonitorExistence() : allExisting_(true) {} //initialization void addForMonitoring(const Zstring& dirName) @@ -116,79 +69,12 @@ private: rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNames, WaitCallback* statusHandler) //throw(FileError) { - /* - #warning cleanup - { - const Zstring formattedDir = zen::getFormattedDirectoryName(dirNames.front()); - - //SE_BACKUP_NAME and SE_RESTORE_NAME <- required by FILE_FLAG_BACKUP_SEMANTICS??? - - //open the directory to watch.... - HANDLE hDir = ::CreateFile(zen::applyLongPathPrefix(formattedDir).c_str(), - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //leaving out last flag may prevent files to be deleted WITHIN monitored dir (http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw_19.html) - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hDir == INVALID_HANDLE_VALUE) - { - const DWORD lastError = ::GetLastError(); - if ( lastError == ERROR_FILE_NOT_FOUND || //no need to check this condition any earlier! - lastError == ERROR_BAD_NETPATH) // - return CHANGE_DIR_MISSING; - - const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + zToWx(formattedDir) + wxT("\""); - throw zen::FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } - - Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hDir); - (void)dummy; //silence warning "unused variable" - - - const size_t bufferSize = sizeof(FILE_NOTIFY_INFORMATION); - boost::scoped_array<char> tmp(new char[bufferSize]); - FILE_NOTIFY_INFORMATION& notifyInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION&>(*tmp.get()); - - DWORD bytesWritten = 0; - - if (!::ReadDirectoryChangesW( - hDir, //__in HANDLE hDirectory, - ¬ifyInfo, //__out LPVOID lpBuffer, - bufferSize, //__in DWORD nBufferLength, - true, //__in BOOL bWatchSubtree, - FILE_NOTIFY_CHANGE_FILE_NAME | //__in DWORD dwNotifyFilter, - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE, - &bytesWritten, //__out_opt LPDWORD lpBytesReturned, - NULL, //__inout_opt LPOVERLAPPED lpOverlapped, - NULL)) //__in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine - { - const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + zToWx(formattedDir) + wxT("\""); - throw zen::FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } - return CHANGE_DETECTED; - } - */ - - - - - - - - - if (dirNames.empty()) //pathological case, but check is needed nevertheless throw zen::FileError(_("A directory input field is empty.")); //detect when volumes are removed/are not available anymore - WatchDirectories dirWatcher; - -#ifdef FFS_WIN - typedef boost::shared_ptr<std::vector<HANDLE> > ChangeNotifList; - ChangeNotifList changeNotifications(new std::vector<HANDLE>, ::cleanUpChangeNotifications); + MonitorExistence checkExist; + std::vector<std::shared_ptr<DirWatcher>> watches; for (std::vector<Zstring>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i) { @@ -197,198 +83,72 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNames, WaitCa if (formattedDir.empty()) throw zen::FileError(_("A directory input field is empty.")); - dirWatcher.addForMonitoring(formattedDir); - - const HANDLE rv = ::FindFirstChangeNotification( - zen::applyLongPathPrefix(formattedDir).c_str(), //__in LPCTSTR lpPathName, - true, //__in BOOL bWatchSubtree, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE); //__in DWORD dwNotifyFilter - - if (rv == INVALID_HANDLE_VALUE) - { - const DWORD lastError = ::GetLastError(); - if ( lastError == ERROR_FILE_NOT_FOUND || //no need to check this condition any earlier! - lastError == ERROR_BAD_NETPATH) // - return CHANGE_DIR_MISSING; - - const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + zToWx(formattedDir) + wxT("\""); - throw zen::FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } - - changeNotifications->push_back(rv); - } - - if (changeNotifications->size() == 0) - throw zen::FileError(_("A directory input field is empty.")); - - - //detect user request for device removal (e.g. usb stick) - class HandleVolumeRemoval : public NotifyRequestDeviceRemoval - { - public: - HandleVolumeRemoval(ChangeNotifList& openHandles) : - NotifyRequestDeviceRemoval(*openHandles), //throw (FileError) - removalRequested(false), - operationComplete(false), - openHandles_(openHandles) {} - - bool requestReceived() const - { - return removalRequested; - } - bool finished() const - { - return operationComplete; - } + checkExist.addForMonitoring(formattedDir); - private: - virtual void onRequestRemoval(HANDLE hnd) //don't throw! + try { - openHandles_.reset(); //free all handles - removalRequested = true; //and make sure they are not used anymore + watches.push_back(std::make_shared<DirWatcher>(formattedDir)); //throw FileError } - virtual void onRemovalFinished(HANDLE hnd, bool successful) //throw()! + catch (zen::FileError&) { - operationComplete = true; + if (!zen::dirExists(formattedDir)) //that's no good locking behavior, but better than nothing + return CHANGE_DIR_MISSING; + throw; } - - bool removalRequested; - bool operationComplete; - ChangeNotifList& openHandles_; - } removalRequest(changeNotifications); - + } while (true) { - //check for changes within directories: - const DWORD rv = ::WaitForMultipleObjects( //NOTE: changeNotifications returns valid pointer, because it cannot be empty in this context - static_cast<DWORD>(changeNotifications->size()), //__in DWORD nCount, - &(*changeNotifications)[0], //__in const HANDLE *lpHandles, - false, //__in BOOL bWaitAll, - UI_UPDATE_INTERVAL); //__in DWORD dwMilliseconds - if (WAIT_OBJECT_0 <= rv && rv < WAIT_OBJECT_0 + changeNotifications->size()) - return CHANGE_DETECTED; //directory change detected - else if (rv == WAIT_FAILED) - throw zen::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + zen::getLastErrorFormatted()); - //else if (rv == WAIT_TIMEOUT) - - if (!dirWatcher.allExisting()) //check for removed devices: + //IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories! + if (!checkExist.allExisting()) //check for removed devices: return CHANGE_DIR_MISSING; - statusHandler->requestUiRefresh(); - - //handle device removal - if (removalRequest.requestReceived()) + try { - const wxMilliClock_t maxwait = wxGetLocalTimeMillis() + 5000; //HandleVolumeRemoval::finished() not guaranteed! - while (!removalRequest.finished() && wxGetLocalTimeMillis() < maxwait) + for (auto iter = watches.begin(); iter != watches.end(); ++iter) { - wxMilliSleep(rts::UI_UPDATE_INTERVAL); - statusHandler->requestUiRefresh(); - } - return CHANGE_DIR_MISSING; - } - } + std::vector<Zstring> changedFiles = (*iter)->getChanges(); //throw FileError -#elif defined FFS_LINUX - std::vector<std::string> fullDirList; //including subdirectories! - - //add all subdirectories - for (std::vector<Zstring>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i) - { - const Zstring formattedDir = zen::getFormattedDirectoryName(*i); - - if (formattedDir.empty()) - throw zen::FileError(_("A directory input field is empty.")); - - dirWatcher.addForMonitoring(formattedDir); + //remove to be ignored changes + changedFiles.erase(std::remove_if(changedFiles.begin(), changedFiles.end(), + [](const Zstring& name) + { + return endsWith(name, Zstr(".ffs_lock")) || //sync.ffs_lock, sync.Del.ffs_lock + endsWith(name, Zstr(".ffs_db")); //sync.ffs_db, .sync.tmp.ffs_db + //no need to ignore temporal recycle bin directory: this must be caused by a file deletion anyway + }), changedFiles.end()); + if (!changedFiles.empty()) + { +/* + std::for_each(changedFiles.begin(), changedFiles.end(), + [](const Zstring& fn) { wxMessageBox(toWx(fn));}); - fullDirList.push_back(formattedDir.c_str()); + const wxString filename = toWx(changedFiles[0]); + ::wxSetEnv(wxT("RTS_CHANGE"), filename); +*/ - try //get all subdirectories - { - DirsOnlyTraverser traverser(fullDirList); - zen::traverseFolder(formattedDir, false, traverser); //don't traverse into symlinks (analog to windows build) + return CHANGE_DETECTED; //directory change detected + } + } } - catch (const zen::FileError&) + catch (FileError&) { - if (!zen::dirExists(formattedDir)) //that's no good locking behavior, but better than nothing + //maybe some error is caused due to some unexpected removal/unavailability of a watched directory? If so we can remedy this error: + if (!checkExist.allExisting()) return CHANGE_DIR_MISSING; - throw; } - } - - try - { - Inotify notifications; - notifications.SetNonBlock(true); - - for (std::vector<std::string>::const_iterator i = fullDirList.begin(); i != fullDirList.end(); ++i) - { - try - { - InotifyWatch newWatch(*i, //dummy object: InotifyWatch may be destructed safely after Inotify::Add() - IN_DONT_FOLLOW | //don't follow symbolic links - IN_ONLYDIR | //watch directories only - IN_CLOSE_WRITE | - IN_CREATE | - IN_DELETE | - IN_DELETE_SELF | - IN_MODIFY | - IN_MOVE_SELF | - IN_MOVED_FROM | - IN_MOVED_TO ); - notifications.Add(newWatch); - } - catch (const InotifyException& e) - { - if (!zen::dirExists(i->c_str())) //that's no good locking behavior, but better than nothing - return CHANGE_DIR_MISSING; - - const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + zToWx(i->c_str()) + wxT("\""); - throw zen::FileError(errorMessage + wxT("\n\n") + zToWx(e.GetMessage().c_str())); - } - } - - - if (notifications.GetWatchCount() == 0) - throw zen::FileError(_("A directory input field is empty.")); - - while (true) - { - notifications.WaitForEvents(); //called in non-blocking mode - - if (notifications.GetEventCount() > 0) - return CHANGE_DETECTED; //directory change detected - if (!dirWatcher.allExisting()) //check for removed devices: - return CHANGE_DIR_MISSING; - - wxMilliSleep(rts::UI_UPDATE_INTERVAL); - statusHandler->requestUiRefresh(); - } - } - catch (const InotifyException& e) - { - throw zen::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + zToWx(e.GetMessage().c_str())); - } - catch (const std::exception& e) - { - throw zen::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + zToWx(e.what())); + wxMilliSleep(rts::UI_UPDATE_INTERVAL); + statusHandler->requestUiRefresh(); } -#endif } +//support for monitoring newly connected directories volumes (e.g.: USB-sticks) void rts::waitForMissingDirs(const std::vector<Zstring>& dirNames, WaitCallback* statusHandler) //throw(FileError) { - //new: support for monitoring newly connected directories volumes (e.g.: USB-sticks) - wxLongLong lastCheck; while (true) diff --git a/RealtimeSync/watcher.h b/RealtimeSync/watcher.h index 46dfc50e..7208e7fb 100644 --- a/RealtimeSync/watcher.h +++ b/RealtimeSync/watcher.h @@ -33,7 +33,7 @@ enum WaitResult CHANGE_DETECTED, CHANGE_DIR_MISSING }; -WaitResult waitForChanges(const std::vector<Zstring>& dirNames444, WaitCallback* statusHandler); //throw(FileError) +WaitResult waitForChanges(const std::vector<Zstring>& dirNames, WaitCallback* statusHandler); //throw(FileError) //wait until all directories become available (again) void waitForMissingDirs(const std::vector<Zstring>& dirNames, WaitCallback* statusHandler); //throw(FileError) diff --git a/RealtimeSync/xml_ffs.cpp b/RealtimeSync/xml_ffs.cpp index 15e6f4c2..3424dea2 100644 --- a/RealtimeSync/xml_ffs.cpp +++ b/RealtimeSync/xml_ffs.cpp @@ -18,42 +18,29 @@ using namespace zen; -#ifdef FFS_WIN -struct CmpNoCase -{ - bool operator()(const wxString& a, const wxString& b) const - { - return a.CmpNoCase(b) < 0; - } -}; -#endif - - xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& batchCfg, const wxString& filename) { xmlAccess::XmlRealConfig output; -#ifdef FFS_WIN - std::set<wxString, CmpNoCase> uniqueFolders; -#elif defined FFS_LINUX - std::set<wxString> uniqueFolders; -#endif + std::set<Zstring, LessFilename> uniqueFolders; //add main folders - uniqueFolders.insert(zToWx(batchCfg.mainCfg.firstPair.leftDirectory)); - uniqueFolders.insert(zToWx(batchCfg.mainCfg.firstPair.rightDirectory)); + uniqueFolders.insert(batchCfg.mainCfg.firstPair.leftDirectory); + uniqueFolders.insert(batchCfg.mainCfg.firstPair.rightDirectory); //additional folders - for (std::vector<zen::FolderPairEnh>::const_iterator i = batchCfg.mainCfg.additionalPairs.begin(); - i != batchCfg.mainCfg.additionalPairs.end(); ++i) + std::for_each(batchCfg.mainCfg.additionalPairs.begin(), batchCfg.mainCfg.additionalPairs.end(), + [&](const FolderPairEnh& fp) { - uniqueFolders.insert(zToWx(i->leftDirectory)); - uniqueFolders.insert(zToWx(i->rightDirectory)); - } + uniqueFolders.insert(fp.leftDirectory); + uniqueFolders.insert(fp.rightDirectory); + }); - uniqueFolders.erase(wxString()); + uniqueFolders.erase(Zstring()); - output.directories.insert(output.directories.end(), uniqueFolders.begin(), uniqueFolders.end()); + output.directories.clear(); + std::transform(uniqueFolders.begin(), uniqueFolders.end(), std::back_inserter(output.directories), + [](const Zstring& fn) { return toWx(fn); }); output.commandline = wxT("\"") + zen::getLauncher() + wxT("\"") + wxT(" \"") + filename + wxT("\""); @@ -62,7 +49,7 @@ xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& bat } -void rts::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config) //throw (xmlAccess::FfsXmlError); +void rts::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config) //throw xmlAccess::FfsXmlError; { if (xmlAccess::getXmlType(filename) != xmlAccess::XML_TYPE_BATCH) { @@ -74,7 +61,7 @@ void rts::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConf xmlAccess::XmlBatchConfig batchCfg; try { - xmlAccess::readConfig(filename, batchCfg); //throw (xmlAccess::FfsXmlError); + xmlAccess::readConfig(filename, batchCfg); //throw xmlAccess::FfsXmlError; } catch (const xmlAccess::FfsXmlError& e) { diff --git a/RealtimeSync/xml_proc.cpp b/RealtimeSync/xml_proc.cpp index 4ddf8bc4..e3d7f270 100644 --- a/RealtimeSync/xml_proc.cpp +++ b/RealtimeSync/xml_proc.cpp @@ -43,7 +43,7 @@ bool isXmlTypeRTS(const XmlDoc& doc) //throw() void xmlAccess::readRealConfig(const wxString& filename, XmlRealConfig& config) { - if (!fileExists(wxToZ(filename))) + if (!fileExists(toZ(filename))) throw FfsXmlError(wxString(_("File does not exist:")) + wxT("\n\"") + filename + wxT("\"")); XmlDoc doc; diff --git a/algorithm.cpp b/algorithm.cpp index 3b210d49..cfc2997a 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -1240,6 +1240,9 @@ private: void operator()(zen::DirMapping& dirObj) const { + if (Eval<strategy>().process(dirObj)) + dirObj.setActive(timeSizeFilter_.matchFolder()); //if date filter is active we deactivate all folders: effectively gets rid of empty folders! + execute(dirObj); //recursion } @@ -1260,11 +1263,10 @@ private: } -void zen::addExcludeFiltering(FolderComparison& folderCmp, const Zstring& excludeFilter) +void zen::addHardFiltering(BaseDirMapping& baseMap, const Zstring& excludeFilter) { - for (std::vector<BaseDirMapping>::iterator i = folderCmp.begin(); i != folderCmp.end(); ++i) - ApplyHardFilter<STRATEGY_AND>(*HardFilter::FilterRef( - new NameFilter(FilterConfig().includeFilter, excludeFilter))).execute(*i); + ApplyHardFilter<STRATEGY_AND>(*HardFilter::FilterRef( + new NameFilter(FilterConfig().includeFilter, excludeFilter))).execute(baseMap); } @@ -1311,7 +1313,10 @@ std::pair<wxString, int> zen::deleteFromGridAndHDPreview( //assemble message con const std::vector<FileSystemObject*>& rowsToDeleteOnRight, const bool deleteOnBothSides) { - wxString filesToDelete; + //fast replacement for wxString modelling exponential growth + typedef Zbase<wchar_t> zxString; //for use with UI texts + + zxString filesToDelete; int totalDelCount = 0; if (deleteOnBothSides) @@ -1320,51 +1325,48 @@ std::pair<wxString, int> zen::deleteFromGridAndHDPreview( //assemble message con std::set<FileSystemObject*> rowsToDelete(rowsToDeleteOnLeft.begin(), rowsToDeleteOnLeft.end()); rowsToDelete.insert(rowsToDeleteOnRight.begin(), rowsToDeleteOnRight.end()); - for (std::set<FileSystemObject*>::const_iterator i = rowsToDelete.begin(); i != rowsToDelete.end(); ++i) + std::for_each(rowsToDelete.begin(), rowsToDelete.end(), + [&](const FileSystemObject* fsObj) { - const FileSystemObject& currObj = *(*i); - - if (!currObj.isEmpty<LEFT_SIDE>()) + if (!fsObj->isEmpty<LEFT_SIDE>()) { - filesToDelete += zToWx(currObj.getFullName<LEFT_SIDE>()) + wxT("\n"); + filesToDelete += utf8CvrtTo<zxString>(fsObj->getFullName<LEFT_SIDE>()) + wxT("\n"); ++totalDelCount; } - if (!currObj.isEmpty<RIGHT_SIDE>()) + if (!fsObj->isEmpty<RIGHT_SIDE>()) { - filesToDelete += zToWx(currObj.getFullName<RIGHT_SIDE>()) + wxT("\n"); + filesToDelete += utf8CvrtTo<zxString>(fsObj->getFullName<RIGHT_SIDE>()) + wxT("\n"); ++totalDelCount; } filesToDelete += wxT("\n"); - } + }); } else //delete selected files only { - for (std::vector<FileSystemObject*>::const_iterator i = rowsToDeleteOnLeft.begin(); i != rowsToDeleteOnLeft.end(); ++i) + std::for_each(rowsToDeleteOnLeft.begin(), rowsToDeleteOnLeft.end(), + [&](const FileSystemObject* fsObj) { - const FileSystemObject& currObj = *(*i); - - if (!currObj.isEmpty<LEFT_SIDE>()) + if (!fsObj->isEmpty<LEFT_SIDE>()) { - filesToDelete += zToWx(currObj.getFullName<LEFT_SIDE>()) + wxT("\n"); + filesToDelete += utf8CvrtTo<zxString>(fsObj->getFullName<LEFT_SIDE>()) + wxT("\n"); ++totalDelCount; } - } + }); - for (std::vector<FileSystemObject*>::const_iterator i = rowsToDeleteOnRight.begin(); i != rowsToDeleteOnRight.end(); ++i) + std::for_each(rowsToDeleteOnRight.begin(), rowsToDeleteOnRight.end(), + [&](const FileSystemObject* fsObj) { - const FileSystemObject& currObj = *(*i); - - if (!currObj.isEmpty<RIGHT_SIDE>()) + if (!fsObj->isEmpty<RIGHT_SIDE>()) { - filesToDelete += zToWx(currObj.getFullName<RIGHT_SIDE>()) + wxT("\n"); + filesToDelete += utf8CvrtTo<zxString>(fsObj->getFullName<RIGHT_SIDE>()) + wxT("\n"); ++totalDelCount; } - } + }); } - return std::make_pair(filesToDelete, totalDelCount); + return std::make_pair(cvrtString<wxString>(filesToDelete), totalDelCount); } diff --git a/algorithm.h b/algorithm.h index 389170ab..ad5d2e30 100644 --- a/algorithm.h +++ b/algorithm.h @@ -29,9 +29,9 @@ void setSyncDirectionRec(SyncDirection newDirection, FileSystemObject& fsObj); / bool allElementsEqual(const FolderComparison& folderCmp); //filtering -void applyFiltering (FolderComparison& folderCmp, const MainConfiguration& mainCfg); //full filter apply -void addExcludeFiltering(FolderComparison& folderCmp, const Zstring& excludeFilter); //exclude additional entries only -void addSoftFiltering (BaseDirMapping& baseMap, const SoftFilter& timeSizeFilter); //exclude additional entries only +void applyFiltering (FolderComparison& folderCmp, const MainConfiguration& mainCfg); //full filter apply +void addHardFiltering(BaseDirMapping& baseMap, const Zstring& excludeFilter); //exclude additional entries only +void addSoftFiltering(BaseDirMapping& baseMap, const SoftFilter& timeSizeFilter); //exclude additional entries only void setActiveStatus(bool newStatus, FolderComparison& folderCmp); //activate or deactivate all rows void setActiveStatus(bool newStatus, FileSystemObject& fsObj); //activate or deactivate row: (not recursively anymore) diff --git a/comparison.cpp b/comparison.cpp index f456e67a..0f2b1dab 100644 --- a/comparison.cpp +++ b/comparison.cpp @@ -9,6 +9,7 @@ #include <stdexcept> #include <memory> #include "shared/global_func.h" +#include "shared/loki/ScopeGuard.h" #include "shared/i18n.h" #include <wx/msgdlg.h> #include <wx/log.h> @@ -24,6 +25,7 @@ #include "library/binary.h" #include "library/cmp_filetime.h" #include "library/lock_holder.h" +#include "library/db_file.h" #ifdef FFS_WIN #include "shared/perf.h" @@ -42,105 +44,91 @@ std::vector<zen::FolderPairCfg> zen::extractCompareCfg(const MainConfiguration& mainCfg.additionalPairs.end()); std::vector<FolderPairCfg> output; - for (std::vector<FolderPairEnh>::const_iterator i = allPairs.begin(); i != allPairs.end(); ++i) - output.push_back( - FolderPairCfg(getFormattedDirectoryName(i->leftDirectory), //ensure they end with common::FILE_NAME_SEPARATOR and replace macros - getFormattedDirectoryName(i->rightDirectory), - normalizeFilters(mainCfg.globalFilter, i->localFilter), - i->altSyncConfig.get() ? i->altSyncConfig->syncConfiguration : mainCfg.syncConfiguration)); + std::transform(allPairs.begin(), allPairs.end(), std::back_inserter(output), + [&](const FolderPairEnh& enhPair) -> FolderPairCfg + { + return FolderPairCfg(getFormattedDirectoryName(enhPair.leftDirectory), //ensure they end with FILE_NAME_SEPARATOR and replace macros + getFormattedDirectoryName(enhPair.rightDirectory), + normalizeFilters(mainCfg.globalFilter, enhPair.localFilter), + mainCfg.handleSymlinks, + enhPair.altSyncConfig.get() ? enhPair.altSyncConfig->syncConfiguration : mainCfg.syncConfiguration); + }); return output; } +class DirCallback; -class BaseDirCallback; - -class DirCallback : public zen::TraverseCallback +struct TraverserConfig { public: - DirCallback(BaseDirCallback* baseCallback, - const Zstring& relNameParentPf, //postfixed with FILE_NAME_SEPARATOR! - DirContainer& output, - ProcessCallback* handler) : - baseCallback_(baseCallback), - relNameParentPf_(relNameParentPf), - output_(output), - statusHandler(handler) {} + TraverserConfig(SymLinkHandling handleSymlinks, + const HardFilter::FilterRef& filter, + std::set<Zstring>& failedReads, + ProcessCallback& handler) : + handleSymlinks_(handleSymlinks), + textScanning(toZ(_("Scanning:")) + Zstr(" \n")), + filterInstance(filter), + statusHandler(handler), + failedReads_(failedReads) {} - virtual ~DirCallback() {} + typedef std::shared_ptr<DirCallback> CallbackPointer; + std::vector<CallbackPointer> callBackBox; //collection of callback pointers to handle ownership - virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details); - virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details); - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName); - virtual void onError(const wxString& errorText); + const SymLinkHandling handleSymlinks_; + const Zstring textScanning; + const HardFilter::FilterRef filterInstance; //always bound! + ProcessCallback& statusHandler; -private: - BaseDirCallback* const baseCallback_; - const Zstring relNameParentPf_; - DirContainer& output_; - ProcessCallback* const statusHandler; + std::set<Zstring>& failedReads_; //relative postfixed names of directories that could not be read (empty for root) }; - -class BaseDirCallback : public DirCallback +class DirCallback : public zen::TraverseCallback { - friend class DirCallback; public: - BaseDirCallback(DirContainer& output, - SymLinkHandling handleSymlinks, - const HardFilter::FilterRef& filter, - ProcessCallback* handler) : - DirCallback(this, Zstring(), output, handler), - handleSymlinks_(handleSymlinks), - textScanning(wxToZ(wxString(_("Scanning:")) + wxT(" \n"))), - filterInstance(filter) {} + DirCallback(TraverserConfig& config, + const Zstring& relNameParentPf, //postfixed with FILE_NAME_SEPARATOR! + DirContainer& output) : + cfg(config), + relNameParentPf_(relNameParentPf), + output_(output) {} - virtual void onFile(const Zchar* shortName, const Zstring& fullName, const TraverseCallback::FileInfo& details); + virtual void onFile (const Zchar* shortName, const Zstring& fullName, const FileInfo& details); + virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details); + virtual ReturnValDir onDir (const Zchar* shortName, const Zstring& fullName); + virtual HandleError onError (const std::wstring& errorText); private: - typedef std::shared_ptr<const DirCallback> CallbackPointer; - - const SymLinkHandling handleSymlinks_; - const Zstring textScanning; - std::vector<CallbackPointer> callBackBox; //collection of callback pointers to handle ownership - - const HardFilter::FilterRef filterInstance; //always bound! + TraverserConfig& cfg; + const Zstring relNameParentPf_; + DirContainer& output_; }; void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) { + const Zstring fileNameShort = shortName; + //do not list the database file(s) sync.ffs_db, sync.x64.ffs_db, etc. or lock files - const Zstring fileNameShort(shortName); - const size_t pos = fileNameShort.rfind(Zchar('.')); - if (pos != Zstring::npos) - { - const Zchar* ending = shortName + pos + 1; - // if (EqualFilename()(ending, SYNC_DB_FILE_ENDING) || - // EqualFilename()(ending, LOCK_FILE_ENDING)) //let's hope this premature performance optimization doesn't bite back! - if (ending == SYNC_DB_FILE_ENDING || // - ending == LOCK_FILE_ENDING) - return; - } + if (endsWith(fileNameShort, SYNC_DB_FILE_ENDING) || + endsWith(fileNameShort, LOCK_FILE_ENDING)) + return; //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") - Zstring statusText = baseCallback_->textScanning; + Zstring statusText = cfg.textScanning; statusText.reserve(statusText.length() + fullName.length() + 2); statusText += Zchar('\"'); statusText += fullName; statusText += Zchar('\"'); //update UI/commandline status information - statusHandler->reportInfo(statusText); + cfg.statusHandler.reportInfo(utf8CvrtTo<wxString>(statusText)); //------------------------------------------------------------------------------------ //apply filter before processing (use relative name!) - if (!baseCallback_->filterInstance->passFileFilter(relNameParentPf_ + fileNameShort)) - { - statusHandler->requestUiRefresh(); + if (!cfg.filterInstance->passFileFilter(relNameParentPf_ + fileNameShort)) return; - } //warning: for windows retrieveFileID is slow as hell! approximately 3 * 10^-4 s per file! //therefore only large files (that take advantage of detection of renaming when synchronizing) should be evaluated! @@ -148,112 +136,99 @@ void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const //#warning this call is NOT acceptable for Linux! // //Linux: retrieveFileID takes about 50% longer in VM! (avoidable because of redundant stat() call!) - // const util::FileID fileIdentifier = details.fileSize >= baseCallback_->detectRenameThreshold_ ? + // const util::FileID fileIdentifier = details.fileSize >= cfg.detectRenameThreshold_ ? // util::retrieveFileID(fullName) : // util::FileID(); output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize)); //add 1 element to the progress indicator - statusHandler->updateProcessedData(1, 0); //NO performance issue at all - //trigger display refresh - statusHandler->requestUiRefresh(); + cfg.statusHandler.updateProcessedData(1, 0); //NO performance issue at all + cfg.statusHandler.requestUiRefresh(); //may throw } void DirCallback::onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) { - if (baseCallback_->handleSymlinks_ == SYMLINK_IGNORE) + if (cfg.handleSymlinks_ == SYMLINK_IGNORE) return; //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") - Zstring statusText = baseCallback_->textScanning; + Zstring statusText = cfg.textScanning; statusText.reserve(statusText.length() + fullName.length() + 2); statusText += Zchar('\"'); statusText += fullName; statusText += Zchar('\"'); //update UI/commandline status information - statusHandler->reportInfo(statusText); + cfg.statusHandler.reportInfo(utf8CvrtTo<wxString>(statusText)); //------------------------------------------------------------------------------------ const Zstring& relName = relNameParentPf_ + shortName; //apply filter before processing (use relative name!) - if (!baseCallback_->filterInstance->passFileFilter(relName)) //always use file filter: Link type may not be "stable" on Linux! - { - statusHandler->requestUiRefresh(); + if (!cfg.filterInstance->passFileFilter(relName)) //always use file filter: Link type may not be "stable" on Linux! return; - } output_.addSubLink(shortName, LinkDescriptor(details.lastWriteTimeRaw, details.targetPath, details.dirLink ? LinkDescriptor::TYPE_DIR : LinkDescriptor::TYPE_FILE)); //add 1 element to the progress indicator - statusHandler->updateProcessedData(1, 0); //NO performance issue at all - //trigger display refresh - statusHandler->requestUiRefresh(); + cfg.statusHandler.updateProcessedData(1, 0); //NO performance issue at all + cfg.statusHandler.requestUiRefresh(); //may throw } TraverseCallback::ReturnValDir DirCallback::onDir(const Zchar* shortName, const Zstring& fullName) { - using common::FILE_NAME_SEPARATOR; - //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") - Zstring statusText = baseCallback_->textScanning; + Zstring statusText = cfg.textScanning; statusText.reserve(statusText.length() + fullName.length() + 2); statusText += Zchar('\"'); statusText += fullName; statusText += Zchar('\"'); //update UI/commandline status information - statusHandler->reportInfo(statusText); + cfg.statusHandler.reportInfo(utf8CvrtTo<wxString>(statusText)); //------------------------------------------------------------------------------------ const Zstring& relName = relNameParentPf_ + shortName; //apply filter before processing (use relative name!) bool subObjMightMatch = true; - if (!baseCallback_->filterInstance->passDirFilter(relName, &subObjMightMatch)) + if (!cfg.filterInstance->passDirFilter(relName, &subObjMightMatch)) { - statusHandler->requestUiRefresh(); - if (!subObjMightMatch) return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //do NOT traverse subdirs } else { - statusHandler->updateProcessedData(1, 0); //NO performance issue at all - statusHandler->requestUiRefresh(); //trigger display refresh + cfg.statusHandler.updateProcessedData(1, 0); //NO performance issue at all + cfg.statusHandler.requestUiRefresh(); //may throw } DirContainer& subDir = output_.addSubDir(shortName); - DirCallback* subDirCallback = new DirCallback(baseCallback_, relName + FILE_NAME_SEPARATOR, subDir, statusHandler); - baseCallback_->callBackBox.push_back(BaseDirCallback::CallbackPointer(subDirCallback)); //handle ownership + TraverserConfig::CallbackPointer subDirCallback = std::make_shared<DirCallback>(cfg, relName + FILE_NAME_SEPARATOR, subDir); + cfg.callBackBox.push_back(subDirCallback); //handle lifetime //attention: ensure directory filtering is applied later to exclude actually filtered directories - return ReturnValDir(Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_CONTINUE>(), *subDirCallback); + return ReturnValDir(Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_CONTINUE>(), *subDirCallback.get()); } -void DirCallback::onError(const wxString& errorText) +DirCallback::HandleError DirCallback::onError(const std::wstring& errorText) { - while (true) + switch (cfg.statusHandler.reportError(errorText)) { - switch (statusHandler->reportError(errorText)) - { - case ErrorHandler::IGNORE_ERROR: - return; - case ErrorHandler::RETRY: - break; //I have to admit "retry" is a bit of a fake here... at least the user has opportunity to abort! - } - } -} + case ProcessCallback::IGNORE_ERROR: + cfg.failedReads_.insert(relNameParentPf_); + return TRAV_ERROR_IGNORE; + case ProcessCallback::RETRY: + return TRAV_ERROR_RETRY; + } -void BaseDirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const TraverseCallback::FileInfo& details) -{ - DirCallback::onFile(shortName, fullName, details); + assert(false); + return TRAV_ERROR_IGNORE; } @@ -261,45 +236,61 @@ void BaseDirCallback::onFile(const Zchar* shortName, const Zstring& fullName, co struct DirBufferKey { DirBufferKey(const Zstring& dirname, - const HardFilter::FilterRef& filterIn) : //filter interface: always bound by design! + const HardFilter::FilterRef& filterIn, //filter interface: always bound by design! + SymLinkHandling handleSymlinks) : directoryName(dirname), - filter(filterIn->isNull() ? //some optimization for "Null" filter - HardFilter::FilterRef(new NullFilter) : - filterIn) {} + filter(filterIn), + handleSymlinks_(handleSymlinks) {} const Zstring directoryName; - const HardFilter::FilterRef filter; //buffering has to consider filtering! + const HardFilter::FilterRef filter; + const SymLinkHandling handleSymlinks_; - bool operator<(const DirBufferKey& b) const + bool operator<(const DirBufferKey& other) const { - if (!EqualFilename()(directoryName, b.directoryName)) - return LessFilename()(directoryName, b.directoryName); + if (handleSymlinks_ != other.handleSymlinks_) + return handleSymlinks_ < other.handleSymlinks_; - return *filter < *b.filter; + if (!EqualFilename()(directoryName, other.directoryName)) + return LessFilename()(directoryName, other.directoryName); + + return *filter < *other.filter; } }; +struct DirBufferValue +{ + DirContainer dirCont; + std::set<Zstring> failedReads; //relative postfixed names of directories that could not be read (empty for root), e.g. access denied, or temporal network drop +}; + + //------------------------------------------------------------------------------------------ class CompareProcess::DirectoryBuffer //buffer multiple scans of the same directories { public: - DirectoryBuffer(SymLinkHandling handleSymlinks, - ProcessCallback& procCallback) : - handleSymlinks_(handleSymlinks), + DirectoryBuffer(ProcessCallback& procCallback) : procCallback_(procCallback) {} - const DirContainer& getDirectoryDescription(const Zstring& directoryPostfixed, const HardFilter::FilterRef& filter); + const DirBufferValue& getDirectoryDescription(const Zstring& directoryPostfixed, const HardFilter::FilterRef& filter, SymLinkHandling handleSymlinks) + { + const DirBufferKey searchKey(directoryPostfixed, filter, handleSymlinks); + + auto iter = buffer.find(searchKey); + if (iter != buffer.end()) + return iter->second; //entry found in buffer; return + else + return insertIntoBuffer(searchKey); //entry not found; create new one + } private: - typedef std::shared_ptr<DirContainer> DirBufferValue; //exception safety: avoid memory leak typedef std::map<DirBufferKey, DirBufferValue> BufferType; - DirContainer& insertIntoBuffer(const DirBufferKey& newKey); + DirBufferValue& insertIntoBuffer(const DirBufferKey& newKey); BufferType buffer; - const SymLinkHandling handleSymlinks_; ProcessCallback& procCallback_; }; //------------------------------------------------------------------------------------------ @@ -310,7 +301,7 @@ class DstHackCallbackImpl : public DstHackCallback { public: DstHackCallbackImpl(ProcessCallback& procCallback) : - textApplyingDstHack(wxToZ(_("Encoding extended time information: %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""))), + textApplyingDstHack(toZ(_("Encoding extended time information: %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""))), procCallback_(procCallback) {} private: @@ -318,8 +309,7 @@ private: { Zstring statusText = textApplyingDstHack; statusText.Replace(Zstr("%x"), filename); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); } const Zstring textApplyingDstHack; @@ -328,21 +318,24 @@ private: #endif -DirContainer& CompareProcess::DirectoryBuffer::insertIntoBuffer(const DirBufferKey& newKey) +DirBufferValue& CompareProcess::DirectoryBuffer::insertIntoBuffer(const DirBufferKey& newKey) { - DirBufferValue baseContainer(new DirContainer); - buffer.insert(std::make_pair(newKey, baseContainer)); + DirBufferValue& bufferVal = buffer[newKey]; //default construct value if (!newKey.directoryName.empty() && zen::dirExists(newKey.directoryName)) //folder existence already checked in startCompareProcess(): do not treat as error when arriving here! { - BaseDirCallback traverser(*baseContainer, - handleSymlinks_, - newKey.filter, - &procCallback_); + TraverserConfig travCfg(newKey.handleSymlinks_, //shared by all(!) instances of DirCallback while traversing a folder hierarchy + newKey.filter, + bufferVal.failedReads, + procCallback_); + + DirCallback traverser(travCfg, + Zstring(), + bufferVal.dirCont); bool followSymlinks = false; - switch (handleSymlinks_) + switch (newKey.handleSymlinks_) { case SYMLINK_IGNORE: followSymlinks = false; //=> symlinks will be reported via onSymlink() where they are excluded @@ -355,29 +348,16 @@ DirContainer& CompareProcess::DirectoryBuffer::insertIntoBuffer(const DirBufferK break; } - std::auto_ptr<zen::DstHackCallback> dstCallback; + DstHackCallback* dstCallbackPtr = NULL; #ifdef FFS_WIN - dstCallback.reset(new DstHackCallbackImpl(procCallback_)); + DstHackCallbackImpl dstCallback(procCallback_); + dstCallbackPtr = &dstCallback; #endif //get all files and folders from directoryPostfixed (and subdirectories) - traverseFolder(newKey.directoryName, followSymlinks, traverser, dstCallback.get()); //exceptions may be thrown! + traverseFolder(newKey.directoryName, followSymlinks, traverser, dstCallbackPtr); //exceptions may be thrown! } - return *baseContainer.get(); -} - - -const DirContainer& CompareProcess::DirectoryBuffer::getDirectoryDescription( - const Zstring& directoryPostfixed, - const HardFilter::FilterRef& filter) -{ - const DirBufferKey searchKey(directoryPostfixed, filter); - - BufferType::const_iterator entryFound = buffer.find(searchKey); - if (entryFound != buffer.end()) - return *entryFound->second.get(); //entry found in buffer; return - else - return insertIntoBuffer(searchKey); //entry not found; create new one + return bufferVal; } @@ -389,7 +369,7 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF bool nonEmptyPairFound = false; //check if user entered at least one folder pair bool partiallyFilledPairFound = false; - const wxString additionalInfo = _("You can ignore this error to consider the directory as empty."); + const std::wstring additionalInfo = _("You can ignore this error to consider the directory as empty."); for (std::vector<FolderPairCfg>::const_iterator i = folderPairsForm.begin(); i != folderPairsForm.end(); ++i) { @@ -404,12 +384,12 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF if (!i->leftDirectoryFmt.empty()) while (!zen::dirExists(i->leftDirectoryFmt)) { - wxString errorMessage = wxString(_("Directory does not exist:")) + wxT("\n") + wxT("\"") + zToWx(i->leftDirectoryFmt) + wxT("\""); - ErrorHandler::Response rv = procCallback.reportError(errorMessage + wxT("\n\n") + additionalInfo + wxT(" ") + zen::getLastErrorFormatted()); + std::wstring errorMessage = _("Directory does not exist:") + "\n" + "\"" + i->leftDirectoryFmt + "\""; + ProcessCallback::Response rv = procCallback.reportError(errorMessage + "\n\n" + additionalInfo + " " + zen::getLastErrorFormatted()); - if (rv == ErrorHandler::IGNORE_ERROR) + if (rv == ProcessCallback::IGNORE_ERROR) break; - else if (rv == ErrorHandler::RETRY) + else if (rv == ProcessCallback::RETRY) ; //continue with loop else throw std::logic_error("Programming Error: Unknown return value! (2)"); @@ -418,11 +398,11 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF if (!i->rightDirectoryFmt.empty()) while (!zen::dirExists(i->rightDirectoryFmt)) { - wxString errorMessage = wxString(_("Directory does not exist:")) + wxT("\n") + wxT("\"") + zToWx(i->rightDirectoryFmt) + wxT("\""); - ErrorHandler::Response rv = procCallback.reportError(errorMessage + wxT("\n\n") + additionalInfo + wxT(" ") + zen::getLastErrorFormatted()); - if (rv == ErrorHandler::IGNORE_ERROR) + std::wstring errorMessage = _("Directory does not exist:") + "\n" + "\"" + i->rightDirectoryFmt + "\""; + ProcessCallback::Response rv = procCallback.reportError(errorMessage + "\n\n" + additionalInfo + " " + zen::getLastErrorFormatted()); + if (rv == ProcessCallback::IGNORE_ERROR) break; - else if (rv == ErrorHandler::RETRY) + else if (rv == ProcessCallback::RETRY) ; //continue with loop else throw std::logic_error("Programming Error: Unknown return value! (3)"); @@ -434,11 +414,11 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF { while (true) { - const ErrorHandler::Response rv = procCallback.reportError(wxString(_("A directory input field is empty.")) + wxT(" \n\n") + - + wxT("(") + additionalInfo + wxT(")")); - if (rv == ErrorHandler::IGNORE_ERROR) + const ProcessCallback::Response rv = procCallback.reportError(_("A directory input field is empty.") + " \n\n" + + + "(" + additionalInfo + ")"); + if (rv == ProcessCallback::IGNORE_ERROR) break; - else if (rv == ErrorHandler::RETRY) + else if (rv == ProcessCallback::RETRY) ; //continue with loop else throw std::logic_error("Programming Error: Unknown return value! (1)"); @@ -470,7 +450,7 @@ wxString checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm if (!i->leftDirectoryFmt.empty() && !i->rightDirectoryFmt.empty()) //empty folders names may be accepted by user { if (EqualDependentDirectory()(i->leftDirectoryFmt, i->rightDirectoryFmt)) //test wheter leftDirectory begins with rightDirectory or the other way round - dependentDirs.push_back(std::make_pair(zToWx(i->leftDirectoryFmt), zToWx(i->rightDirectoryFmt))); + dependentDirs.push_back(std::make_pair(toWx(i->leftDirectoryFmt), toWx(i->rightDirectoryFmt))); } wxString warnignMsg; @@ -478,10 +458,10 @@ wxString checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm if (!dependentDirs.empty()) { warnignMsg = _("Directories are dependent! Be careful when setting up synchronization rules:"); - for (DirDirList::const_iterator i = dependentDirs.begin(); i != dependentDirs.end(); ++i) - warnignMsg += wxString(wxT("\n\n")) + - wxT("\"") + i->first + wxT("\"\n") + - wxT("\"") + i->second + wxT("\""); + for (auto i = dependentDirs.begin(); i != dependentDirs.end(); ++i) + warnignMsg += wxString(L"\n\n") + + "\"" + i->first + "\"\n" + + "\"" + i->second + "\""; } return warnignMsg; } @@ -491,48 +471,40 @@ wxString checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm class CmpCallbackImpl : public CompareCallback { public: - CmpCallbackImpl(ProcessCallback& pc, zen::UInt64& bytesComparedLast) : + CmpCallbackImpl(ProcessCallback& pc, UInt64& bytesReported) : pc_(pc), - m_bytesComparedLast(bytesComparedLast) {} + bytesReported_(bytesReported) {} - virtual void updateCompareStatus(zen::UInt64 totalBytesTransferred) + virtual void updateCompareStatus(UInt64 totalBytesTransferred) { - //called every 512 kB - //inform about the (differential) processed amount of data - pc_.updateProcessedData(0, to<zen::Int64>(totalBytesTransferred) - to<zen::Int64>(m_bytesComparedLast)); - m_bytesComparedLast = totalBytesTransferred; + pc_.updateProcessedData(0, to<Int64>(totalBytesTransferred) - to<Int64>(bytesReported_)); //throw()! -> this ensures client and service provider are in sync! + bytesReported_ = totalBytesTransferred; // - pc_.requestUiRefresh(); //exceptions may be thrown here! + pc_.requestUiRefresh(); //may throw } private: ProcessCallback& pc_; - zen::UInt64& m_bytesComparedLast; + UInt64& bytesReported_; }; -bool filesHaveSameContentUpdating(const Zstring& filename1, const Zstring& filename2, zen::UInt64 totalBytesToCmp, ProcessCallback& pc) +bool filesHaveSameContentUpdating(const Zstring& filename1, const Zstring& filename2, UInt64 totalBytesToCmp, ProcessCallback& pc) { - zen::UInt64 bytesComparedLast; //amount of bytes that have been compared and communicated to status handler + UInt64 bytesReported; //amount of bytes that have been compared and communicated to status handler - CmpCallbackImpl callback(pc, bytesComparedLast); + //in error situation: undo communication of processed amount of data + Loki::ScopeGuard guardStatistics = Loki::MakeGuard([&]() { pc.updateProcessedData(0, -1 * to<Int64>(bytesReported)); }); - bool sameContent = true; - try - { - sameContent = filesHaveSameContent(filename1, filename2, callback); //throw FileError - } - catch (...) - { - //error situation: undo communication of processed amount of data - pc.updateProcessedData(0, -1 * to<zen::Int64>(bytesComparedLast)); - throw; - } + CmpCallbackImpl callback(pc, bytesReported); + bool sameContent = filesHaveSameContent(filename1, filename2, callback); //throw FileError //inform about the (remaining) processed amount of data - pc.updateProcessedData(0, to<zen::Int64>(totalBytesToCmp) - to<zen::Int64>(bytesComparedLast)); + pc.updateProcessedData(0, to<Int64>(totalBytesToCmp) - to<Int64>(bytesReported)); + bytesReported = totalBytesToCmp; + guardStatistics.Dismiss(); return sameContent; } @@ -584,19 +556,21 @@ private: //############################################################################################################################# -CompareProcess::CompareProcess(SymLinkHandling handleSymlinks, - size_t fileTimeTol, +CompareProcess::CompareProcess(size_t fileTimeTol, xmlAccess::OptionalDialogs& warnings, ProcessCallback& handler) : fileTimeTolerance(fileTimeTol), m_warnings(warnings), procCallback(handler), - txtComparingContentOfFiles(wxToZ(_("Comparing content of files %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)) + txtComparingContentOfFiles(toZ(_("Comparing content of files %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)) { - directoryBuffer.reset(new DirectoryBuffer(handleSymlinks, handler)); + directoryBuffer.reset(new DirectoryBuffer(handler)); } +CompareProcess::~CompareProcess() {} //std::auto_ptr does not work with forward declarations (Or we need a non-inline ~CompareProcess())! + + void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& directoryPairs, const CompareVariant cmpVar, FolderComparison& output) @@ -651,13 +625,6 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc { const FolderPairCfg& fpCfg = directoryPairs[j - output_tmp.begin()]; - //attention: some filtered directories are still in the comparison result! (see include filter handling!) - if (!fpCfg.filter.nameFilter->isNull()) - RemoveFilteredDirs(*fpCfg.filter.nameFilter).execute(*j); //remove all excluded directories (but keeps those serving as parent folders for not excl. elements) - - //apply soft filtering / hard filter already applied - addSoftFiltering(*j, fpCfg.filter.timeSizeFilter); - //set initial sync-direction class RedetermineCallback : public DeterminationProblem { @@ -684,7 +651,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc } catch (const std::bad_alloc& e) { - procCallback.reportFatalError(wxString(_("Memory allocation failed!")) + wxT(" ") + wxString::FromAscii(e.what())); + procCallback.reportFatalError(_("Memory allocation failed!") + " " + e.what()); } catch (const std::exception& e) { @@ -694,13 +661,13 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc //--------------------assemble conflict descriptions--------------------------- -//check for very old dates or dates in the future +//check for very old dates or date2s in the future wxString getConflictInvalidDate(const Zstring& fileNameFull, zen::Int64 utcTime) { wxString msg = _("File %x has an invalid date!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(fileNameFull) + wxT("\"")); - msg += wxString(wxT("\n\n")) + _("Date") + wxT(": ") + utcTimeToLocalString(utcTime); - return wxString(_("Conflict detected:")) + wxT("\n") + msg; + replace(msg, L"%x", wxString(L"\"") + fileNameFull + "\""); + msg += wxString(L"\n\n") + _("Date") + ": " + utcTimeToLocalString(utcTime); + return wxString(_("Conflict detected:")) + "\n" + msg; } @@ -728,13 +695,13 @@ wxString getConflictSameDateDiffSize(const FileMapping& fileObj) const wxString right = wxT("--> "); wxString msg = _("Files %x have the same date but a different size!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(fileObj.getRelativeName<LEFT_SIDE>()) + wxT("\"")); - msg += wxT("\n\n"); - msg += left + wxT("\t") + _("Date") + wxT(": ") + utcTimeToLocalString(fileObj.getLastWriteTime<LEFT_SIDE>()) + - wxT(" \t") + _("Size") + wxT(": ") + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + wxT("\n"); - msg += right + wxT("\t") + _("Date") + wxT(": ") + utcTimeToLocalString(fileObj.getLastWriteTime<RIGHT_SIDE>()) + - wxT(" \t") + _("Size") + wxT(": ") + toStringSep(fileObj.getFileSize<RIGHT_SIDE>()); - return wxString(_("Conflict detected:")) + wxT("\n") + msg; + replace(msg, wxT("%x"), wxString(wxT("\"")) + fileObj.getRelativeName<LEFT_SIDE>() + "\""); + msg += L"\n\n"; + msg += left + "\t" + _("Date") + ": " + utcTimeToLocalString(fileObj.getLastWriteTime<LEFT_SIDE>()) + + " \t" + _("Size") + ": " + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + wxT("\n"); + msg += right + "\t" + _("Date") + ": " + utcTimeToLocalString(fileObj.getLastWriteTime<RIGHT_SIDE>()) + + " \t" + _("Size") + ": " + toStringSep(fileObj.getFileSize<RIGHT_SIDE>()); + return _("Conflict detected:") + "\n" + msg; } @@ -778,8 +745,8 @@ void CompareProcess::categorizeSymlinkByTime(SymLinkMapping* linkObj) const } else { - wxString conflictMsg = wxString(_("Conflict detected:")) + wxT("\n") + _("Symlinks %x have the same date but a different target!"); - conflictMsg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(linkObj->getRelativeName<LEFT_SIDE>()) + wxT("\"")); + wxString conflictMsg = _("Conflict detected:") + "\n" + _("Symlinks %x have the same date but a different target!"); + replace(conflictMsg, L"%x", wxString(L"\"") + linkObj->getRelativeName<LEFT_SIDE>() + "\""); linkObj->setCategoryConflict(conflictMsg); } break; @@ -803,7 +770,7 @@ void CompareProcess::categorizeSymlinkByTime(SymLinkMapping* linkObj) const } -void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairs, FolderComparison& output) const +void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairs, FolderComparison& output) { output.reserve(output.size() + directoryPairs.size()); @@ -818,7 +785,7 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directo //do basis scan and retrieve files existing on both sides as "compareCandidates" std::vector<FileMapping*> uncategorizedFiles; std::vector<SymLinkMapping*> uncategorizedLinks; - performBaseComparison(output.back(), uncategorizedFiles, uncategorizedLinks); + performComparison(*pair, output.back(), uncategorizedFiles, uncategorizedLinks); //finish symlink categorization std::for_each(uncategorizedLinks.begin(), uncategorizedLinks.end(), boost::bind(&CompareProcess::categorizeSymlinkByTime, this, _1)); @@ -901,7 +868,7 @@ void CompareProcess::categorizeSymlinkByContent(SymLinkMapping* linkObj) const } -void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& directoryPairs, FolderComparison& output) const +void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& directoryPairs, FolderComparison& output) { //PERF_START; std::vector<FileMapping*> compareCandidates; @@ -919,7 +886,7 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director std::vector<SymLinkMapping*> uncategorizedLinks; //do basis scan and retrieve candidates for binary comparison (files existing on both sides) - performBaseComparison(output.back(), compareCandidates, uncategorizedLinks); + performComparison(*pair, output.back(), compareCandidates, uncategorizedLinks); //finish symlink categorization std::for_each(uncategorizedLinks.begin(), uncategorizedLinks.end(), boost::bind(&CompareProcess::categorizeSymlinkByContent, this, _1)); @@ -958,14 +925,11 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director Zstring statusText = txtComparingContentOfFiles; statusText.Replace(Zstr("%x"), line->getRelativeName<LEFT_SIDE>(), false); - procCallback.reportInfo(statusText); + procCallback.reportInfo(utf8CvrtTo<wxString>(statusText)); //check files that exist in left and right model but have different content while (true) { - //trigger display refresh - procCallback.requestUiRefresh(); - try { if (filesHaveSameContentUpdating(line->getFullName<LEFT_SIDE>(), @@ -984,18 +948,19 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director line->setCategory<FILE_DIFFERENT>(); procCallback.updateProcessedData(2, 0); //processed data is communicated in subfunctions! + procCallback.requestUiRefresh(); //may throw break; } catch (FileError& error) { - ErrorHandler::Response rv = procCallback.reportError(error.msg()); - if (rv == ErrorHandler::IGNORE_ERROR) + ProcessCallback::Response rv = procCallback.reportError(error.msg()); + if (rv == ProcessCallback::IGNORE_ERROR) { line->setCategoryConflict(wxString(_("Conflict detected:")) + wxT("\n") + _("Comparing files by content failed.")); break; } - else if (rv == ErrorHandler::RETRY) + else if (rv == ProcessCallback::RETRY) ; //continue with loop else throw std::logic_error("Programming Error: Unknown return value!"); @@ -1170,8 +1135,11 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right } -//undefinedFiles and undefinedLinks are appended only! -void CompareProcess::performBaseComparison(BaseDirMapping& output, std::vector<FileMapping*>& undefinedFiles, std::vector<SymLinkMapping*>& undefinedLinks) const +//create comparison result table and fill category except for files existing on both sides: undefinedFiles and undefinedLinks are appended! +void CompareProcess::performComparison(const FolderPairCfg& fpCfg, + BaseDirMapping& output, + std::vector<FileMapping*>& undefinedFiles, + std::vector<SymLinkMapping*>& undefinedLinks) { assert(output.useSubDirs(). empty()); assert(output.useSubLinks().empty()); @@ -1180,19 +1148,45 @@ void CompareProcess::performBaseComparison(BaseDirMapping& output, std::vector<F //PERF_START; //scan directories - const DirContainer& directoryLeft = directoryBuffer->getDirectoryDescription( - output.getBaseDir<LEFT_SIDE>(), - output.getFilter()); - - const DirContainer& directoryRight = directoryBuffer->getDirectoryDescription( - output.getBaseDir<RIGHT_SIDE>(), - output.getFilter()); + const DirBufferValue& bufValueLeft = directoryBuffer->getDirectoryDescription( + output.getBaseDir<LEFT_SIDE>(), + fpCfg.filter.nameFilter, + fpCfg.handleSymlinks); + const DirBufferValue& bufValueRight = directoryBuffer->getDirectoryDescription( + output.getBaseDir<RIGHT_SIDE>(), + fpCfg.filter.nameFilter, + fpCfg.handleSymlinks); - procCallback.reportInfo(wxToZ(_("Generating file list..."))); + procCallback.reportInfo(_("Generating file list...")); procCallback.forceUiRefresh(); //keep total number of scanned files up to date //PERF_STOP; + MergeSides(undefinedFiles, undefinedLinks).execute(bufValueLeft.dirCont, bufValueRight.dirCont, output); + + //##################### in/exclude rows according to filtering ##################### + + //attention: some filtered directories are still in the comparison result! (see include filter handling!) + if (!fpCfg.filter.nameFilter->isNull()) + RemoveFilteredDirs(*fpCfg.filter.nameFilter).execute(output); //remove all excluded directories (but keeps those serving as parent folders for not excl. elements) - MergeSides(undefinedFiles, undefinedLinks).execute(directoryLeft, directoryRight, output); + //apply soft filtering / hard filter already applied + addSoftFiltering(output, fpCfg.filter.timeSizeFilter); + + //properly handle (user-ignored) traversing errors: just uncheck them, no need to physically delete them (<automatic> mode will be grateful) + std::set<Zstring> failedReads; + failedReads.insert(bufValueLeft .failedReads.begin(), bufValueLeft .failedReads.end()); + failedReads.insert(bufValueRight.failedReads.begin(), bufValueRight.failedReads.end()); + + if (!failedReads.empty()) + { + Zstring filterFailedRead; + //exclude subfolders only + std::for_each(failedReads.begin(), failedReads.end(), + [&](const Zstring& relDirPf) { filterFailedRead += relDirPf + Zstr("?*\n"); }); + //note: relDirPf is empty for base dir, otherwise postfixed! e.g. "subdir\" + + addHardFiltering(output, filterFailedRead); + } + //################################################################################## } diff --git a/comparison.h b/comparison.h index f3c9ac52..444b3c3c 100644 --- a/comparison.h +++ b/comparison.h @@ -22,15 +22,18 @@ struct FolderPairCfg FolderPairCfg(const Zstring& leftDir, //must be formatted folder pairs! const Zstring& rightDir, const NormalizedFilter& filterIn, + SymLinkHandling handleSymlinksIn, const SyncConfig& syncCfg) : leftDirectoryFmt(leftDir), rightDirectoryFmt(rightDir), filter(filterIn), + handleSymlinks(handleSymlinksIn), syncConfiguration(syncCfg) {} Zstring leftDirectoryFmt; //resolved folder pairs!!! Zstring rightDirectoryFmt; // NormalizedFilter filter; + SymLinkHandling handleSymlinks; SyncConfig syncConfiguration; }; @@ -41,28 +44,31 @@ std::vector<FolderPairCfg> extractCompareCfg(const MainConfiguration& mainCfg); class CompareProcess { public: - CompareProcess(SymLinkHandling handleSymlinks, - size_t fileTimeTol, + CompareProcess(size_t fileTimeTol, xmlAccess::OptionalDialogs& warnings, ProcessCallback& handler); void startCompareProcess(const std::vector<FolderPairCfg>& directoryPairs, const CompareVariant cmpVar, FolderComparison& output); +~CompareProcess(); private: - void compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output) const; - void compareByContent( const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output) const; + void compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); + void compareByContent( const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); //create comparison result table and fill category except for files existing on both sides: undefinedFiles and undefinedLinks are appended! - void performBaseComparison(BaseDirMapping& output, std::vector<FileMapping*>& undefinedFiles, std::vector<SymLinkMapping*>& undefinedLinks) const; - void categorizeSymlinkByTime(SymLinkMapping* linkObj) const; void categorizeSymlinkByContent(SymLinkMapping* linkObj) const; + void performComparison(const FolderPairCfg& fpCfg, + BaseDirMapping& output, + std::vector<FileMapping*>& undefinedFiles, + std::vector<SymLinkMapping*>& undefinedLinks); + //buffer accesses to the same directories; useful when multiple folder pairs are used class DirectoryBuffer; - std::shared_ptr<DirectoryBuffer> directoryBuffer; //std::auto_ptr does not work with forward declarations (Or we need a non-inline ~CompareProcess())! + std::unique_ptr<DirectoryBuffer> directoryBuffer; const size_t fileTimeTolerance; //max allowed file time deviation diff --git a/file_hierarchy.cpp b/file_hierarchy.cpp index 672fd1b1..9e7d4d4e 100644 --- a/file_hierarchy.cpp +++ b/file_hierarchy.cpp @@ -199,20 +199,4 @@ SyncOperation FileSystemObject::getSyncOperation( } return SO_DO_NOTHING; //dummy -} - - -const Zstring& zen::getSyncDBFilename() -{ - //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! - //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 - static Zstring output = Zstring(Zstr("sync.")) + SYNC_DB_FILE_ENDING; -#elif defined FFS_LINUX - //files beginning with dots are hidden e.g. in Nautilus - static Zstring output = Zstring(Zstr(".sync.")) + SYNC_DB_FILE_ENDING; -#endif - return output; -} +}
\ No newline at end of file diff --git a/file_hierarchy.h b/file_hierarchy.h index 75db798d..1b4f244b 100644 --- a/file_hierarchy.h +++ b/file_hierarchy.h @@ -8,7 +8,6 @@ #define FILEHIERARCHY_H_INCLUDED #include "shared/zstring.h" -#include "shared/system_constants.h" #include <map> #include <set> #include <vector> @@ -131,11 +130,6 @@ struct DirContainer //------------------------------------------------------------------ -//save/load full directory information -const Zstring& getSyncDBFilename(); //get short filename of database file -const Zstring SYNC_DB_FILE_ENDING = Zstr("ffs_db"); - -//------------------------------------------------------------------ /* class hierarchy: FileSystemObject HierarchyObject @@ -195,7 +189,7 @@ public: protected: //constructor used by DirMapping HierarchyObject(const HierarchyObject& parent, const Zstring& shortName) : - relNamePf( parent.getRelativeNamePf() + shortName + common::FILE_NAME_SEPARATOR), + relNamePf( parent.getRelativeNamePf() + shortName + FILE_NAME_SEPARATOR), baseDirLeft( parent.baseDirLeft), baseDirRight(parent.baseDirRight) {} @@ -246,10 +240,10 @@ public: filter(filterIn) {} const HardFilter::FilterRef& getFilter() const; - template <SelectedSide side> Zstring getDBFilename() const; virtual void swap(); private: + //this member is currently not used by the business logic -> may be removed! HardFilter::FilterRef filter; }; @@ -735,7 +729,7 @@ const Zstring& FileSystemObject::getObjShortName() const inline const Zstring FileSystemObject::getParentRelativeName() const { - return nameBuffer.parentRelNamePf.BeforeLast(common::FILE_NAME_SEPARATOR); //returns empty string if char not found + return nameBuffer.parentRelNamePf.BeforeLast(FILE_NAME_SEPARATOR); //returns empty string if char not found } @@ -1014,14 +1008,6 @@ const HardFilter::FilterRef& BaseDirMapping::getFilter() const } -template <SelectedSide side> -inline -Zstring BaseDirMapping::getDBFilename() const -{ - return getBaseDir<side>() + getSyncDBFilename(); -} - - inline void FileMapping::swap() { diff --git a/library/custom_grid.cpp b/library/custom_grid.cpp index c2b87b5d..97b608fb 100644 --- a/library/custom_grid.cpp +++ b/library/custom_grid.cpp @@ -5,7 +5,6 @@ // ************************************************************************** // #include "custom_grid.h" -#include "../shared/system_constants.h" #include "resources.h" #include <wx/dc.h> #include "../shared/util.h" @@ -283,16 +282,16 @@ protected: switch (colType_) { case xmlAccess::FULL_PATH: - value = zToWx(fileObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + value = toWx(fileObj.getFullName<side>().BeforeLast(FILE_NAME_SEPARATOR)); break; case xmlAccess::FILENAME: //filename - value = zToWx(fileObj.getShortName<side>()); + value = toWx(fileObj.getShortName<side>()); break; case xmlAccess::REL_PATH: //relative path - value = zToWx(fileObj.getParentRelativeName()); + value = toWx(fileObj.getParentRelativeName()); break; case xmlAccess::DIRECTORY: - value = zToWx(fileObj.getBaseDirPf<side>()); + value = toWx(fileObj.getBaseDirPf<side>()); break; case xmlAccess::SIZE: //file size value = zen::toStringSep(fileObj.getFileSize<side>()); @@ -301,7 +300,7 @@ protected: value = zen::utcTimeToLocalString(fileObj.getLastWriteTime<side>()); break; case xmlAccess::EXTENSION: //file extension - value = zToWx(fileObj.getExtension<side>()); + value = toWx(fileObj.getExtension<side>()); break; } } @@ -311,16 +310,16 @@ protected: switch (colType_) { case xmlAccess::FULL_PATH: - value = zToWx(linkObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + value = toWx(linkObj.getFullName<side>().BeforeLast(FILE_NAME_SEPARATOR)); break; case xmlAccess::FILENAME: //filename - value = zToWx(linkObj.getShortName<side>()); + value = toWx(linkObj.getShortName<side>()); break; case xmlAccess::REL_PATH: //relative path - value = zToWx(linkObj.getParentRelativeName()); + value = toWx(linkObj.getParentRelativeName()); break; case xmlAccess::DIRECTORY: - value = zToWx(linkObj.getBaseDirPf<side>()); + value = toWx(linkObj.getBaseDirPf<side>()); break; case xmlAccess::SIZE: //file size value = _("<Symlink>"); @@ -339,16 +338,16 @@ protected: switch (colType_) { case xmlAccess::FULL_PATH: - value = zToWx(dirObj.getFullName<side>()); + value = toWx(dirObj.getFullName<side>()); break; case xmlAccess::FILENAME: - value = zToWx(dirObj.getShortName<side>()); + value = toWx(dirObj.getShortName<side>()); break; case xmlAccess::REL_PATH: - value = zToWx(dirObj.getParentRelativeName()); + value = toWx(dirObj.getParentRelativeName()); break; case xmlAccess::DIRECTORY: - value = zToWx(dirObj.getBaseDirPf<side>()); + value = toWx(dirObj.getBaseDirPf<side>()); break; case xmlAccess::SIZE: //file size value = _("<Directory>"); @@ -1264,7 +1263,8 @@ public: icon = IconBuffer::getFileIcon(); //better than nothing } - dc.DrawIcon(icon, rectShrinked.GetX() + LEFT_BORDER, rectShrinked.GetY()); + if (icon.IsOk()) + dc.DrawIcon(icon, rectShrinked.GetX() + LEFT_BORDER, rectShrinked.GetY()); //----------------------------------------------------------------------------------------------- //save status of last icon load -> used for async. icon loading @@ -1374,20 +1374,20 @@ void CustomGridRim::setTooltip(const wxMouseEvent& event) virtual void visit(const FileMapping& fileObj) { - tipMsg_ = zToWx(fileObj.getRelativeName<side>()) + wxT("\n") + - _("Size") + wxT(": ") + zen::formatFilesizeToShortString(fileObj.getFileSize<side>()) + wxT("\n") + - _("Date") + wxT(": ") + zen::utcTimeToLocalString(fileObj.getLastWriteTime<side>()); + tipMsg_ = toWx(fileObj.getRelativeName<side>()) + "\n" + + _("Size") + ": " + zen::formatFilesizeToShortString(fileObj.getFileSize<side>()) + "\n" + + _("Date") + ": " + zen::utcTimeToLocalString(fileObj.getLastWriteTime<side>()); } virtual void visit(const SymLinkMapping& linkObj) { - tipMsg_ = zToWx(linkObj.getRelativeName<side>()) + wxT("\n") + - _("Date") + wxT(": ") + zen::utcTimeToLocalString(linkObj.getLastWriteTime<side>()); + tipMsg_ = toWx(linkObj.getRelativeName<side>()) + "\n" + + _("Date") + ": " + zen::utcTimeToLocalString(linkObj.getLastWriteTime<side>()); } virtual void visit(const DirMapping& dirObj) { - tipMsg_ = zToWx(dirObj.getRelativeName<side>()); + tipMsg_ = toWx(dirObj.getRelativeName<side>()); } wxString& tipMsg_; diff --git a/library/db_file.cpp b/library/db_file.cpp index 1d48dbdf..ec1c4464 100644 --- a/library/db_file.cpp +++ b/library/db_file.cpp @@ -30,10 +30,29 @@ namespace { //------------------------------------------------------------------------------------------------------------------------------- const char FILE_FORMAT_DESCR[] = "FreeFileSync"; -const int FILE_FORMAT_VER = 6; +const int FILE_FORMAT_VER = 7; //------------------------------------------------------------------------------------------------------------------------------- +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! + //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 + Zstring dbname = Zstring(Zstr("sync")) + (tempfile ? Zstr(".tmp") : Zstr("")) + SYNC_DB_FILE_ENDING; +#elif defined FFS_LINUX + //files beginning with dots are hidden e.g. in Nautilus + Zstring dbname = Zstring(Zstr(".sync")) + (tempfile ? Zstr(".tmp") : Zstr("")) + SYNC_DB_FILE_ENDING; +#endif + + return baseMap.getBaseDir<side>() + dbname; +} + + + class FileInputStreamDB : public FileInputStream { public: @@ -45,7 +64,7 @@ public: Read(formatDescr, sizeof(formatDescr)); //throw (FileError) if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr)) - throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + zToWx(filename) + wxT("\"")); + throw FileError(_("Incompatible synchronization database format:") + " \n" + "\"" + filename + "\""); } private: @@ -138,115 +157,162 @@ private: namespace { typedef std::string UniqueId; -typedef std::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation -typedef std::map<UniqueId, MemoryStreamPtr> DirectoryTOC; //list of streams ordered by a UUID pointing to their partner database -typedef std::pair<UniqueId, DirectoryTOC> DbStreamData; //header data: UUID representing this database, item data: list of dir-streams +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 } -/* Example -left side right side ---------- ---------- -DB-ID 123 <-\ /-> DB-ID 567 - \/ -Partner-ID 111 /\ Partner-ID 222 -Partner-ID 567 _/ \_ Partner-ID 123 - ... ... -*/ class ReadFileStream : public zen::ReadInputStream { public: - ReadFileStream(wxInputStream& stream, const wxString& filename, DbStreamData& output, int& versionId) : ReadInputStream(stream, filename) + ReadFileStream(wxInputStream& stream, const wxString& filename, StreamMapping& streamList, bool leftSide) : ReadInputStream(stream, filename) { //|------------------------------------------------------------------------------------- //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t | //|------------------------------------------------------------------------------------- boost::int32_t version = readNumberC<boost::int32_t>(); - if (version != FILE_FORMAT_VER) //read file format version - throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + filename + wxT("\"")); - versionId = version; - //read DB id - const CharArray tmp = readArrayC(); - output.first.assign(tmp->begin(), tmp->end()); +#ifndef _MSC_VER +#warning remove this check after migration! +#endif + if (version != 6) //migrate! + + if (version != FILE_FORMAT_VER) //read file format version + throw FileError(_("Incompatible synchronization database format:") + " \n" + "\"" + filename.c_str() + "\""); + - DirectoryTOC& dbList = output.second; - dbList.clear(); +#ifndef _MSC_VER +#warning remove this case after migration! +#endif - boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair - while (dbCount-- != 0) + if (version == 6) { - //DB id of partner databases - const CharArray tmp2 = readArrayC(); - const std::string partnerID(tmp2->begin(), tmp2->end()); + streamList.clear(); + + //read DB id + const CharArray tmp = readArrayC(); + std::string mainId(tmp->begin(), tmp->end()); + + boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair + while (dbCount-- != 0) + { + //DB id of partner databases + const CharArray tmp2 = readArrayC(); + const std::string partnerID(tmp2->begin(), tmp2->end()); - CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation) + CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation) - dbList.insert(std::make_pair(partnerID, buffer)); + if (leftSide) + streamList.insert(std::make_pair(partnerID + mainId, buffer)); + else + streamList.insert(std::make_pair(mainId + partnerID, buffer)); + } + } + else + { + streamList.clear(); + + boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair + while (dbCount-- != 0) + { + //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) + + streamList.insert(std::make_pair(sessionID, buffer)); + } } } }; +namespace +{ +StreamMapping loadStreams(const Zstring& filename, -DbStreamData loadFile(const Zstring& filename) //throw (FileError) +#ifndef _MSC_VER +#warning remove this parameter after migration! +#endif + bool leftSide) //throw (FileError) { if (!zen::fileExists(filename)) - throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database files is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(filename) + wxT("\"")); + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + " \n\n" + + _("One of the FreeFileSync database files is not yet existing:") + " \n" + + "\"" + filename + "\""); - //read format description (uncompressed) - FileInputStreamDB uncompressed(filename); //throw (FileError) + try + { + //read format description (uncompressed) + FileInputStreamDB uncompressed(filename); //throw (FileError) - wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); + wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); - DbStreamData output; - int versionId = 0; - ReadFileStream (input, zToWx(filename), output, versionId); - return output; + StreamMapping streamList; + ReadFileStream(input, toWx(filename), streamList, leftSide); + return streamList; + } + catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file + { + throw FileError(_("Error reading from synchronization database:") + " (bad_alloc)"); + } } -std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw (FileError) +DirInfoPtr parseStream(const std::vector<char>& stream, const Zstring& fileName) //throw FileError -> return value always bound! { - const Zstring fileNameLeft = baseMapping.getDBFilename<LEFT_SIDE>(); - const Zstring fileNameRight = baseMapping.getDBFilename<RIGHT_SIDE>(); - try { - //read file data: db ID + mapping of partner-ID/DirInfo-stream - const DbStreamData dbEntriesLeft = ::loadFile(fileNameLeft); - const DbStreamData dbEntriesRight = ::loadFile(fileNameRight); - - //find associated DirInfo-streams - DirectoryTOC::const_iterator dbLeft = dbEntriesLeft.second.find(dbEntriesRight.first); //find left db-entry that corresponds to right database - DirectoryTOC::const_iterator dbRight = dbEntriesRight.second.find(dbEntriesLeft.first); //find left db-entry that corresponds to right database - - if (dbLeft == dbEntriesLeft.second.end()) - throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(fileNameLeft) + wxT("\"")); + //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, toWx(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:") + " (bad_alloc)"); + } +} +} - if (dbRight == dbEntriesRight.second.end()) - throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(fileNameRight) + wxT("\"")); - //read streams into DirInfo - std::shared_ptr<DirInformation> dirInfoLeft(new DirInformation); - wxMemoryInputStream buffer(&(*dbLeft->second)[0], dbLeft->second->size()); //convert char-array to inputstream: no copying, ownership not transferred - ReadDirInfo(buffer, zToWx(fileNameLeft), *dirInfoLeft); //read file/dir information +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); - std::shared_ptr<DirInformation> dirInfoRight(new DirInformation); - wxMemoryInputStream buffer2(&(*dbRight->second)[0], dbRight->second->size()); //convert char-array to inputstream: no copying, ownership not transferred - ReadDirInfo(buffer2, zToWx(fileNameRight), *dirInfoRight); //read file/dir information + //read file data: list of session ID + DirInfo-stream + const StreamMapping streamListLeft = ::loadStreams(fileNameLeft, true); //throw (FileError) + const StreamMapping streamListRight = ::loadStreams(fileNameRight, false); //throw (FileError) - return std::make_pair(dirInfoLeft, dirInfoRight); - } - catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file + //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) { - throw FileError(wxString(_("Error reading from synchronization database:")) + wxT(" (bad_alloc)")); + auto iterRight = streamListRight.find(iterLeft->first); + if (iterRight != streamListRight.end()) + { + streamLeft = iterLeft; + streamRight = iterRight; + break; + } } + + if (streamLeft == streamListLeft .end() || + streamRight == streamListRight.end() || + !streamLeft ->second.get() || + !streamRight->second.get()) + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + " \n\n" + + _("No matching synchronization session found in database files:") + " \n" + + "\"" + fileNameLeft + "\"\n" + + "\"" + fileNameRight + "\""); + //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); } @@ -375,21 +441,16 @@ private: class WriteFileStream : public WriteOutputStream { public: - WriteFileStream(const DbStreamData& input, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) + WriteFileStream(const StreamMapping& streamList, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) { //save file format version writeNumberC<boost::int32_t>(FILE_FORMAT_VER); - //write DB id - writeArrayC(std::vector<char>(input.first.begin(), input.first.end())); - - const DirectoryTOC& dbList = input.second; + writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(streamList.size())); //number of database records: one for each sync-pair - writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(dbList.size())); //number of database records: one for each sync-pair - - for (DirectoryTOC::const_iterator i = dbList.begin(); i != dbList.end(); ++i) + for (StreamMapping::const_iterator i = streamList.begin(); i != streamList.end(); ++i) { - //DB id of partner database + //sync session id writeArrayC(std::vector<char>(i->first.begin(), i->first.end())); //write DirInformation stream @@ -400,7 +461,7 @@ public: //save/load DirContainer -void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (FileError) +void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw (FileError) { { //write format description (uncompressed) @@ -414,7 +475,7 @@ void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (Fi 6 1,77 MB - 613 ms 9 (maximal compression) 1,74 MB - 3330 ms */ - WriteFileStream(dbStream, zToWx(filename), output); + WriteFileStream(streamList, toWx(filename), output); } //(try to) hide database file #ifdef FFS_WIN @@ -423,133 +484,132 @@ void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (Fi } -bool entryExisting(const DirectoryTOC& table, const UniqueId& newKey, const MemoryStreamPtr& newValue) +bool equalEntry(const MemoryStreamPtr& lhs, const MemoryStreamPtr& rhs) { - DirectoryTOC::const_iterator iter = table.find(newKey); - if (iter == table.end()) - return false; - - if (!newValue.get() || !iter->second.get()) - return newValue.get() == iter->second.get(); + if (!lhs.get() || !rhs.get()) + return lhs.get() == rhs.get(); - return *newValue == *iter->second; + return *lhs == *rhs; } void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileError) { //transactional behaviour! write to tmp files first - const Zstring fileNameLeftTmp = baseMapping.getDBFilename<LEFT_SIDE>() + Zstr(".tmp"); - const Zstring fileNameRightTmp = baseMapping.getDBFilename<RIGHT_SIDE>() + Zstr(".tmp");; + const Zstring dbNameLeftTmp = getDBFilename<LEFT_SIDE >(baseMapping, true); + const Zstring dbNameRightTmp = getDBFilename<RIGHT_SIDE>(baseMapping, true); + + const Zstring dbNameLeft = getDBFilename<LEFT_SIDE >(baseMapping); + const Zstring dbNameRight = getDBFilename<RIGHT_SIDE>(baseMapping); //delete old tmp file, if necessary -> throws if deletion fails! - removeFile(fileNameLeftTmp); // - removeFile(fileNameRightTmp); //throw (FileError) + removeFile(dbNameLeftTmp); // + removeFile(dbNameRightTmp); //throw (FileError) - //load old database files... + //(try to) load old database files... + StreamMapping streamListLeft; + StreamMapping streamListRight; - //read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw! - DbStreamData dbEntriesLeft; - try - { - dbEntriesLeft = ::loadFile(baseMapping.getDBFilename<LEFT_SIDE>()); - } - catch(FileError&) + try //read file data: list of session ID + DirInfo-stream { - //if error occurs: just overwrite old file! User is already informed about issues right after comparing! - //dbEntriesLeft has empty mapping, but already a DB-ID! - dbEntriesLeft.first = util::generateGUID(); + streamListLeft = ::loadStreams(dbNameLeft, true); } - - //read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw! - DbStreamData dbEntriesRight; + catch(FileError&) {} //if error occurs: just overwrite old file! User is already informed about issues right after comparing! try { - dbEntriesRight = ::loadFile(baseMapping.getDBFilename<RIGHT_SIDE>()); + streamListRight = ::loadStreams(dbNameRight, false); } - catch(FileError&) + catch(FileError&) {} + + //find associated session: there can be at most one session within intersection of left and right ids + StreamMapping::iterator streamLeft = streamListLeft .end(); + StreamMapping::iterator streamRight = streamListRight.end(); + for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft) { - dbEntriesRight.first = util::generateGUID(); + auto iterRight = streamListRight.find(iterLeft->first); + if (iterRight != streamListRight.end()) + { + streamLeft = iterLeft; + streamRight = iterRight; + break; + } } - //(try to) read old DirInfo - std::shared_ptr<DirInformation> oldDirInfoLeft; + DirInfoPtr oldDirInfoLeft; + DirInfoPtr oldDirInfoRight; try { - DirectoryTOC::const_iterator iter = dbEntriesLeft.second.find(dbEntriesRight.first); - if (iter != dbEntriesLeft.second.end()) - if (iter->second.get()) - { - const std::vector<char>& memStream = *iter->second; - wxMemoryInputStream buffer(&memStream[0], memStream.size()); //convert char-array to inputstream: no copying, ownership not transferred - std::shared_ptr<DirInformation> dirInfoTmp = std::make_shared<DirInformation>(); - ReadDirInfo(buffer, zToWx(baseMapping.getDBFilename<LEFT_SIDE>()), *dirInfoTmp); //read file/dir information - oldDirInfoLeft = dirInfoTmp; - } + if (streamLeft != streamListLeft .end() && + streamRight != streamListRight.end() && + streamLeft ->second.get() && + streamRight->second.get()) + { + oldDirInfoLeft = parseStream(*streamLeft ->second, dbNameLeft); //throw FileError + oldDirInfoRight = parseStream(*streamRight->second, dbNameRight); //throw FileError + } } - catch(FileError&) {} //if error occurs: just overwrite old file! User is already informed about issues right after comparing! - - std::shared_ptr<DirInformation> oldDirInfoRight; - try + catch(FileError&) { - DirectoryTOC::const_iterator iter = dbEntriesRight.second.find(dbEntriesLeft.first); - if (iter != dbEntriesRight.second.end()) - if (iter->second.get()) - { - const std::vector<char>& memStream = *iter->second; - wxMemoryInputStream buffer(&memStream[0], memStream.size()); //convert char-array to inputstream: no copying, ownership not transferred - std::shared_ptr<DirInformation> dirInfoTmp = std::make_shared<DirInformation>(); - ReadDirInfo(buffer, zToWx(baseMapping.getDBFilename<RIGHT_SIDE>()), *dirInfoTmp); //read file/dir information - oldDirInfoRight = dirInfoTmp; - } + //if error occurs: just overwrite old file! User is already informed about issues right after comparing! + oldDirInfoLeft .reset(); //read both or none! + oldDirInfoRight.reset(); // } - catch(FileError&) {} - //create new database entries - MemoryStreamPtr dbEntryLeft(new std::vector<char>); + MemoryStreamPtr newStreamLeft = std::make_shared<std::vector<char>>(); { wxMemoryOutputStream buffer; - DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL; - SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, zToWx(baseMapping.getDBFilename<LEFT_SIDE>()), buffer); - dbEntryLeft->resize(buffer.GetSize()); //convert output stream to char-array - buffer.CopyTo(&(*dbEntryLeft)[0], buffer.GetSize()); // + const DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL; + SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, toWx(dbNameLeft), buffer); + newStreamLeft->resize(buffer.GetSize()); //convert output stream to char-array + buffer.CopyTo(&(*newStreamLeft)[0], buffer.GetSize()); // } - MemoryStreamPtr dbEntryRight(new std::vector<char>); + MemoryStreamPtr newStreamRight = std::make_shared<std::vector<char>>(); { wxMemoryOutputStream buffer; - DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL; - SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, zToWx(baseMapping.getDBFilename<RIGHT_SIDE>()), buffer); - dbEntryRight->resize(buffer.GetSize()); //convert output stream to char-array - buffer.CopyTo(&(*dbEntryRight)[0], buffer.GetSize()); // + const DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL; + SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, toWx(dbNameRight), buffer); + newStreamRight->resize(buffer.GetSize()); //convert output stream to char-array + buffer.CopyTo(&(*newStreamRight)[0], buffer.GetSize()); // } - //create/update DirInfo-streams + //check if there is some work to do at all { - const bool updateRequiredLeft = !entryExisting(dbEntriesLeft. second, dbEntriesRight.first, dbEntryLeft); - const bool updateRequiredRight = !entryExisting(dbEntriesRight.second, dbEntriesLeft. first, dbEntryRight); + const bool updateRequiredLeft = streamLeft == streamListLeft .end() || !equalEntry(newStreamLeft, streamLeft ->second); + const bool updateRequiredRight = streamRight == streamListRight.end() || !equalEntry(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; } - dbEntriesLeft .second[dbEntriesRight.first] = dbEntryLeft; - dbEntriesRight.second[dbEntriesLeft .first] = dbEntryRight; + + //create/update DirInfo-streams + std::string sessionID = util::generateGUID(); + + //erase old session data + if (streamLeft != streamListLeft.end()) + streamListLeft.erase(streamLeft); + if (streamRight != streamListRight.end()) + streamListRight.erase(streamRight); + + //fill in new + streamListLeft .insert(std::make_pair(sessionID, newStreamLeft)); + streamListRight.insert(std::make_pair(sessionID, newStreamRight)); //write (temp-) files... - Loki::ScopeGuard guardTempFileLeft = Loki::MakeGuard(&zen::removeFile, fileNameLeftTmp); - saveFile(dbEntriesLeft, fileNameLeftTmp); //throw (FileError) + Loki::ScopeGuard guardTempFileLeft = Loki::MakeGuard(&zen::removeFile, dbNameLeftTmp); + saveFile(streamListLeft, dbNameLeftTmp); //throw (FileError) - Loki::ScopeGuard guardTempFileRight = Loki::MakeGuard(&zen::removeFile, fileNameRightTmp); - saveFile(dbEntriesRight, fileNameRightTmp); //throw (FileError) + Loki::ScopeGuard guardTempFileRight = Loki::MakeGuard(&zen::removeFile, dbNameRightTmp); + saveFile(streamListRight, dbNameRightTmp); //throw (FileError) //operation finished: rename temp files -> this should work transactionally: //if there were no write access, creation of temp files would have failed - removeFile(baseMapping.getDBFilename<LEFT_SIDE>()); - removeFile(baseMapping.getDBFilename<RIGHT_SIDE>()); - renameFile(fileNameLeftTmp, baseMapping.getDBFilename<LEFT_SIDE>()); //throw (FileError); - renameFile(fileNameRightTmp, baseMapping.getDBFilename<RIGHT_SIDE>()); //throw (FileError); + removeFile(dbNameLeft); + removeFile(dbNameRight); + renameFile(dbNameLeftTmp, dbNameLeft); //throw (FileError); + renameFile(dbNameRightTmp, dbNameRight); //throw (FileError); guardTempFileLeft. Dismiss(); //no need to delete temp file anymore guardTempFileRight.Dismiss(); // diff --git a/library/db_file.h b/library/db_file.h index 5c03ee96..a68e6bcf 100644 --- a/library/db_file.h +++ b/library/db_file.h @@ -12,6 +12,8 @@ namespace zen { +const Zstring SYNC_DB_FILE_ENDING = Zstr(".ffs_db"); + void saveToDisk(const BaseDirMapping& baseMapping); //throw (FileError) struct DirInformation diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp index 835db4ef..1775026b 100644 --- a/library/dir_lock.cpp +++ b/library/dir_lock.cpp @@ -11,7 +11,6 @@ #include "../shared/last_error.h" #include "../shared/boost_thread_wrap.h" //include <boost/thread.hpp> #include "../shared/loki/ScopeGuard.h" -#include "../shared/system_constants.h" #include "../shared/guid.h" #include "../shared/file_io.h" #include "../shared/assert_static.h" @@ -47,20 +46,12 @@ const int LOCK_FORMAT_VER = 1; //lock file format version typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class } +//worker thread class LifeSigns { public: LifeSigns(const BasicString& lockfilename) : //throw()!!! siehe SharedDirLock() - lockfilename_(lockfilename) //thread safety: make deep copy! - { - threadObj = boost::thread(boost::cref(*this)); //localize all thread logic to this class! - } - - ~LifeSigns() - { - threadObj.interrupt(); //thread lifetime is subset of this instances's life - threadObj.join(); - } + lockfilename_(lockfilename) {} //thread safety: make deep copy! void operator()() const //thread entry { @@ -129,11 +120,8 @@ public: } private: - LifeSigns(const LifeSigns&); //just be sure this ref-counting Zstring doesn't bite - LifeSigns& operator=(const LifeSigns&); // - - boost::thread threadObj; - const BasicString lockfilename_; //used by worker thread only! Not ref-counted! + //make sure this instance is safely copyable! + const BasicString lockfilename_; //thread local! Not ref-counted! }; @@ -147,8 +135,7 @@ void deleteLockFile(const Zstring& filename) //throw (FileError) if (::unlink(filename.c_str()) != 0) #endif { - wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + getLastErrorFormatted()); + throw FileError(_("Error deleting file:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted()); } } @@ -162,8 +149,7 @@ zen::UInt64 getLockFileSize(const Zstring& filename) //throw (FileError, ErrorNo { const DWORD lastError = ::GetLastError(); - wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - errorMessage += wxT("\n\n") + getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted(lastError); if (lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_PATH_NOT_FOUND) @@ -182,8 +168,7 @@ zen::UInt64 getLockFileSize(const Zstring& filename) //throw (FileError, ErrorNo { const int lastError = errno; - wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - errorMessage += wxT("\n\n") + getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted(lastError); if (lastError == ENOENT) throw ErrorNotExisting(errorMessage); @@ -196,13 +181,13 @@ zen::UInt64 getLockFileSize(const Zstring& filename) //throw (FileError, ErrorNo } -Zstring deleteAbandonedLockName(const Zstring& lockfilename) +Zstring deleteAbandonedLockName(const Zstring& lockfilename) //make sure to NOT change file ending! { - const size_t pos = lockfilename.rfind(common::FILE_NAME_SEPARATOR); //search from end + const size_t pos = lockfilename.rfind(FILE_NAME_SEPARATOR); //search from end return pos == Zstring::npos ? Zstr("Del.") + lockfilename : Zstring(lockfilename.c_str(), pos + 1) + //include path separator Zstr("Del.") + - lockfilename.AfterLast(common::FILE_NAME_SEPARATOR); //returns the whole string if ch not found + lockfilename.AfterLast(FILE_NAME_SEPARATOR); //returns the whole string if ch not found } @@ -319,6 +304,7 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe 0); //__in DWORD th32ProcessID if (snapshot == INVALID_HANDLE_VALUE) return PROC_STATUS_NO_IDEA; + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, snapshot); (void)dummy; //silence warning "unused variable" @@ -371,10 +357,10 @@ std::string retrieveLockId(const Zstring& lockfilename) //throw (FileError, Erro void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw (FileError) { - Zstring infoMsg; - infoMsg = wxToZ(_("Waiting while directory is locked (%x)...")); - infoMsg.Replace(Zstr("%x"), Zstr("\"") + lockfilename + Zstr("\"")); - if (callback) callback->reportInfo(infoMsg); + std::wstring infoMsg = _("Waiting while directory is locked (%x)..."); + replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + "\""); + if (callback) + callback->reportInfo(infoMsg); //--------------------------------------------------------------- try { @@ -428,16 +414,15 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr long remainingSeconds = ((DETECT_EXITUS_INTERVAL - (wxGetLocalTimeMillis() - lockSilentStart)) / 1000).ToLong(); remainingSeconds = std::max(0L, remainingSeconds); - Zstring remSecMsg = wxToZ(_P("1 sec", "%x sec", remainingSeconds)); - remSecMsg.Replace(Zstr("%x"), Zstring::fromNumber(remainingSeconds)); - callback->reportInfo(infoMsg + Zstr(" ") + remSecMsg); + std::wstring remSecMsg = _P("1 sec", "%x sec", remainingSeconds); + replace(remSecMsg, L"%x", toString<std::wstring>(remainingSeconds)); + callback->reportInfo(infoMsg + " " + remSecMsg); } else callback->reportInfo(infoMsg); //emit a message in any case (might clear other one) } } } - } catch (const ErrorNotExisting&) { @@ -471,10 +456,7 @@ bool tryLock(const Zstring& lockfilename) //throw (FileError) if (::GetLastError() == ERROR_FILE_EXISTS) return false; else - { - wxString errorMessage = wxString(_("Error setting directory lock:")) + wxT("\n\"") + zToWx(lockfilename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + getLastErrorFormatted()); - } + throw FileError(_("Error setting directory lock:") + "\n\"" + lockfilename + "\"" + "\n\n" + getLastErrorFormatted()); } ::CloseHandle(fileHandle); @@ -487,11 +469,7 @@ bool tryLock(const Zstring& lockfilename) //throw (FileError) if (errno == EEXIST) return false; else - { - wxString errorMessage = wxString(_("Error setting directory lock:")) + wxT("\n\"") + zToWx(lockfilename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + getLastErrorFormatted()); - } - + throw FileError(_("Error setting directory lock:") + "\n\"" + lockfilename + "\"" + "\n\n" + getLastErrorFormatted()); } ::close(fileHandle); #endif @@ -516,12 +494,13 @@ public: while (!::tryLock(lockfilename)) //throw (FileError) ::waitOnDirLock(lockfilename, callback); // - emitLifeSigns.reset(new LifeSigns(lockfilename.c_str())); //throw()! ownership of lockfile not yet managed! + threadObj = boost::thread(LifeSigns(lockfilename.c_str())); } ~SharedDirLock() { - emitLifeSigns.reset(); + threadObj.interrupt(); //thread lifetime is subset of this instances's life + threadObj.join(); ::releaseLock(lockfilename_); //throw () } @@ -532,7 +511,7 @@ private: const Zstring lockfilename_; - std::auto_ptr<LifeSigns> emitLifeSigns; + boost::thread threadObj; }; diff --git a/library/dir_lock.h b/library/dir_lock.h index 5d51d698..f4720e61 100644 --- a/library/dir_lock.h +++ b/library/dir_lock.h @@ -1,7 +1,6 @@ #ifndef DIR_LOCK_H_INCLUDED #define DIR_LOCK_H_INCLUDED -#include "../shared/zstring.h" #include "../shared/file_error.h" #include <memory> @@ -10,7 +9,7 @@ struct DirLockCallback //while waiting for the lock { virtual ~DirLockCallback() {} virtual void requestUiRefresh() = 0; //allowed to throw exceptions - virtual void reportInfo(const Zstring& text) = 0; + virtual void reportInfo(const std::wstring& text) = 0; }; /* diff --git a/library/error_log.cpp b/library/error_log.cpp index a78b1c9a..eef8572a 100644 --- a/library/error_log.cpp +++ b/library/error_log.cpp @@ -73,14 +73,19 @@ wxString ErrorLogging::formatMessage(const Entry& msg) break; } - const wxString prefix = wxString(wxT("[")) + wxDateTime(msg.time).FormatTime() + wxT("] ") + typeName + wxT(": "); + const wxString prefix = wxString(L"[") + wxDateTime(msg.time).FormatTime() + L"] " + typeName + L": "; wxString formattedText = prefix; - for (wxString::const_iterator i = msg.message.begin(); i != msg.message.end(); ++i) + for (auto i = msg.message.begin(); i != msg.message.end(); ++i) if (*i == wxChar('\n')) { - formattedText += wxString(wxChar('\n')).Pad(prefix.size(), wxChar(' '), true); - while (*++i == wxChar('\n')) //remove duplicate newlines + formattedText += L'\n'; + + wxString blanks; + blanks.resize(prefix.size(), L' '); + formattedText += blanks; + + while (*++i == L'\n') //remove duplicate newlines ; --i; } diff --git a/library/error_log.h b/library/error_log.h index 1acc0f8c..323a4297 100644 --- a/library/error_log.h +++ b/library/error_log.h @@ -10,7 +10,6 @@ #include <wx/string.h> #include <vector> #include <map> -#include "../shared/zstring.h" namespace zen @@ -37,7 +36,7 @@ private: { MessageType type; time_t time; - wxString message; + wxString message; }; static wxString formatMessage(const Entry& msg); diff --git a/library/hard_filter.cpp b/library/hard_filter.cpp index 194fe41c..e96d32fa 100644 --- a/library/hard_filter.cpp +++ b/library/hard_filter.cpp @@ -10,7 +10,6 @@ #include <set> #include <stdexcept> #include <vector> -#include "../shared/system_constants.h" #include "../structures.h" #include <boost/bind.hpp> #include "../shared/loki/LokiTypeInfo.h" @@ -58,7 +57,6 @@ HardFilter::FilterRef HardFilter::loadFilter(wxInputStream& stream) //-------------------------------------------------------------------------------------------------- -inline void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, std::set<Zstring>& directoryFilter) { Zstring filterFormatted = filtername; @@ -70,17 +68,17 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st //Linux DOES distinguish between upper/lower-case: nothing to do here #endif - const Zstring sepAsterisk = Zstring(common::FILE_NAME_SEPARATOR) + Zchar('*'); - const Zstring sepQuestionMark = Zstring(common::FILE_NAME_SEPARATOR) + Zchar('?'); - const Zstring asteriskSep = Zstring(Zstr('*')) + common::FILE_NAME_SEPARATOR; - const Zstring questionMarkSep = Zstring(Zstr('?')) + common::FILE_NAME_SEPARATOR; + const Zstring sepAsterisk = Zstring(FILE_NAME_SEPARATOR) + Zchar('*'); + const Zstring sepQuestionMark = Zstring(FILE_NAME_SEPARATOR) + Zchar('?'); + const Zstring asteriskSep = Zstring(Zstr('*')) + FILE_NAME_SEPARATOR; + const Zstring questionMarkSep = Zstring(Zstr('?')) + FILE_NAME_SEPARATOR; //-------------------------------------------------------------------------------------------------- //add some syntactic sugar: handle beginning of filtername - if (filterFormatted.StartsWith(common::FILE_NAME_SEPARATOR)) + if (filterFormatted.StartsWith(FILE_NAME_SEPARATOR)) { //remove leading separators (keep BEFORE test for Zstring::empty()!) - filterFormatted = filterFormatted.AfterFirst(common::FILE_NAME_SEPARATOR); + filterFormatted = filterFormatted.AfterFirst(FILE_NAME_SEPARATOR); } else if (filterFormatted.StartsWith(asteriskSep) || // *\abc filterFormatted.StartsWith(questionMarkSep)) // ?\abc @@ -90,9 +88,9 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st //-------------------------------------------------------------------------------------------------- //even more syntactic sugar: handle end of filtername - if (filterFormatted.EndsWith(common::FILE_NAME_SEPARATOR)) + if (filterFormatted.EndsWith(FILE_NAME_SEPARATOR)) { - const Zstring candidate = filterFormatted.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring candidate = filterFormatted.BeforeLast(FILE_NAME_SEPARATOR); if (!candidate.empty()) directoryFilter.insert(candidate); //only relevant for directory filtering } @@ -102,7 +100,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st fileFilter.insert( filterFormatted); directoryFilter.insert(filterFormatted); - const Zstring candidate = filterFormatted.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring candidate = filterFormatted.BeforeLast(FILE_NAME_SEPARATOR); if (!candidate.empty()) directoryFilter.insert(candidate); //only relevant for directory filtering } @@ -235,19 +233,20 @@ std::vector<Zstring> compoundStringToFilter(const Zstring& filterString) //delimiters may be ';' or '\n' std::vector<Zstring> output; - const std::vector<Zstring> blocks = filterString.Split(Zchar(';')); - for (std::vector<Zstring>::const_iterator i = blocks.begin(); i != blocks.end(); ++i) + const std::vector<Zstring> blocks = split(filterString, Zchar(';')); + std::for_each(blocks.begin(), blocks.end(), + [&](const Zstring& item) { - const std::vector<Zstring> blocks2 = i->Split(Zchar('\n')); + const std::vector<Zstring> blocks2 = split(item, Zchar('\n')); - for (std::vector<Zstring>::const_iterator j = blocks2.begin(); j != blocks2.end(); ++j) + std::for_each(blocks2.begin(), blocks2.end(), + [&](Zstring entry) { - Zstring entry = *j; - entry.Trim(); + trim(entry); if (!entry.empty()) output.push_back(entry); - } - } + }); + }); return output; } @@ -261,12 +260,12 @@ NameFilter::NameFilter(const Zstring& includeFilter, const Zstring& excludeFilte //load filter into vectors of strings //delimiters may be ';' or '\n' - const std::vector<Zstring> includeList = compoundStringToFilter(includeFilter); - const std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter); + const std::vector<Zstring>& includeList = compoundStringToFilter(includeFilter); + const std::vector<Zstring>& excludeList = compoundStringToFilter(excludeFilter); //setup include/exclude filters for files and directories - std::for_each(includeList.begin(), includeList.end(), boost::bind(addFilterEntry, _1, boost::ref(filterFileIn), boost::ref(filterFolderIn))); - std::for_each(excludeList.begin(), excludeList.end(), boost::bind(addFilterEntry, _1, boost::ref(filterFileEx), boost::ref(filterFolderEx))); + std::for_each(includeList.begin(), includeList.end(), [&](const Zstring& entry) { addFilterEntry(entry, filterFileIn, filterFolderIn); }); + std::for_each(excludeList.begin(), excludeList.end(), [&](const Zstring& entry) { addFilterEntry(entry, filterFileEx, filterFolderEx); }); } @@ -306,7 +305,7 @@ bool NameFilter::passDirFilter(const Zstring& relDirname, bool* subObjMightMatch { if (subObjMightMatch) { - const Zstring& subNameBegin = nameFormatted + common::FILE_NAME_SEPARATOR; //const-ref optimization + const Zstring& subNameBegin = nameFormatted + FILE_NAME_SEPARATOR; //const-ref optimization *subObjMightMatch = matchesFilterBegin(subNameBegin, filterFileIn) || //might match a file in subdirectory matchesFilterBegin(subNameBegin, filterFolderIn); //or another subdirectory diff --git a/library/icon_buffer.cpp b/library/icon_buffer.cpp index 1b1706d2..91487498 100644 --- a/library/icon_buffer.cpp +++ b/library/icon_buffer.cpp @@ -26,8 +26,6 @@ using namespace zen; - - const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to buffer //--------------------------------------------------------------------------------------------------- @@ -80,7 +78,7 @@ public: IconHolder(HandleType handle = 0) : handle_(handle) {} //take ownership! //icon holder has value semantics! - IconHolder(const IconHolder& other) : handle_(other.handle_ == 0 ? 0 : + IconHolder(const IconHolder& other) : handle_(other.handle_ == NULL ? NULL : #ifdef FFS_WIN ::CopyIcon(other.handle_) #elif defined FFS_LINUX @@ -96,7 +94,7 @@ public: ~IconHolder() { - if (handle_ != 0) + if (handle_ != NULL) #ifdef FFS_WIN ::DestroyIcon(handle_); #elif defined FFS_LINUX @@ -111,7 +109,7 @@ public: wxIcon toWxIcon() const //copy HandleType, caller needs to take ownership! { - if (handle_ == 0) + if (handle_ == NULL) return wxNullIcon; IconHolder clone(*this); @@ -123,7 +121,7 @@ public: #elif defined FFS_LINUX // newIcon.SetPixbuf(clone.handle_); // transfer ownership!! #endif // - clone.handle_ = 0; // + clone.handle_ = NULL; // return newIcon; } @@ -213,7 +211,7 @@ IconHolder getAssociatedIconByExt(const BasicString& extension) #endif -const wxIcon& getDirectoryIcon() //one folder icon should be sufficient... +const wxIcon& getDirectoryIcon() { static wxIcon folderIcon; @@ -246,7 +244,7 @@ const wxIcon& getDirectoryIcon() //one folder icon should be sufficient... } -const wxIcon& getFileIcon() //in case one folder icon is sufficient... +const wxIcon& getFileIcon() { static wxIcon fileIcon; @@ -292,128 +290,87 @@ const wxIcon& getFileIcon() //in case one folder icon is sufficient... //################################################################################################################################################ -class Buffer +//---------------------- Shared Data ------------------------- +struct WorkLoad { -public: - //methods used by gui and worker thread - bool requestFileIcon(const Zstring& fileName, wxIcon* icon = NULL); + std::vector<BasicString> filesToLoad; //processes last elements of vector first! + boost::mutex mutex; + boost::condition_variable condition; //signal event: data for processing available +}; - //methods used by worker thread - void insertIntoBuffer(const BasicString& entryName, const IconHolder& icon); +typedef std::map<BasicString, IconHolder, LessFilename> NameIconMap; //entryName/icon -> ATTENTION: avoid ref-counting for this shared data structure! +typedef std::queue<BasicString> IconDbSequence; //entryName -private: - //--------------------------------------------------------------------------------------------------- - typedef std::map<BasicString, IconHolder, LessFilename> IconDB; //entryName/icon -> ATTENTION: avoid ref-counting for this shared data structure! - typedef std::queue<BasicString> IconDbSequence; //entryName - //--------------------------------------------------------------------------------------------------- - - //---------------------- Shared Data ------------------------- - boost::mutex lockIconDB; - IconDB iconBuffer; //use synchronisation when accessing this! +struct Buffer +{ + boost::mutex lockAccess; + NameIconMap iconMappping; //use synchronisation when accessing this! IconDbSequence iconSequence; //save sequence of buffer entry to delete oldest elements - //------------------------------------------------------------ }; +//------------------------------------------------------------ -bool Buffer::requestFileIcon(const Zstring& fileName, wxIcon* icon) +bool requestFileIcon(Buffer& buf, const Zstring& fileName, wxIcon* icon = NULL) { - boost::lock_guard<boost::mutex> dummy(lockIconDB); + boost::lock_guard<boost::mutex> dummy(buf.lockAccess); #ifdef FFS_WIN //"pricey" extensions are stored with fullnames and are read from disk, while cheap ones require just the extension - const BasicString extension = getFileExtension(fileName.c_str()); - const BasicString searchString = isPriceyExtension(extension) ? fileName.c_str() : extension.c_str(); - IconDB::const_iterator i = iconBuffer.find(searchString); + const BasicString extension = getFileExtension(BasicString(fileName)); + const BasicString searchString = isPriceyExtension(extension) ? BasicString(fileName) : extension; + auto iter = buf.iconMappping.find(searchString); #elif defined FFS_LINUX - IconDB::const_iterator i = iconBuffer.find(fileName.c_str()); + auto iter = buf.iconMappping.find(BasicString(fileName)); #endif - if (i == iconBuffer.end()) + if (iter == buf.iconMappping.end()) return false; if (icon != NULL) - *icon = i->second.toWxIcon(); - + *icon = iter->second.toWxIcon(); return true; } -void Buffer::insertIntoBuffer(const BasicString& entryName, const IconHolder& icon) //called by worker thread +void insertIntoBuffer(Buffer& buf, const BasicString& entryName, const IconHolder& icon) //called by worker thread { - boost::lock_guard<boost::mutex> dummy(lockIconDB); + boost::lock_guard<boost::mutex> dummy(buf.lockAccess); //thread saftey: icon uses ref-counting! But is NOT shared with main thread! - const std::pair<IconDB::iterator, bool> rc = iconBuffer.insert(std::make_pair(entryName, icon)); + auto rc = buf.iconMappping.insert(std::make_pair(entryName, icon)); if (rc.second) //if insertion took place - iconSequence.push(entryName); //note: sharing Zstring with IconDB!!! + buf.iconSequence.push(entryName); //note: sharing Zstring with IconDB!!! - assert(iconBuffer.size() == iconSequence.size()); + assert(buf.iconMappping.size() == buf.iconSequence.size()); //remove elements if buffer becomes too big: - if (iconBuffer.size() > BUFFER_SIZE_MAX) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) + if (buf.iconMappping.size() > BUFFER_SIZE_MAX) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) { //remove oldest element - iconBuffer.erase(iconSequence.front()); - iconSequence.pop(); + buf.iconMappping.erase(buf.iconSequence.front()); + buf.iconSequence.pop(); } } - - //################################################################################################################################################ -class WorkerThread + +class WorkerThread //lifetime is part of icon buffer { public: - WorkerThread(Buffer& iconBuff) : iconBuffer(iconBuff) - { - threadObj = boost::thread(boost::ref(*this)); //localize all thread logic to this class! - } - - ~WorkerThread() - { - setWorkload(std::vector<Zstring>()); //make sure interruption point is always reached! - threadObj.interrupt(); - threadObj.join(); - } - - void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved + WorkerThread(const std::shared_ptr<WorkLoad>& workload, + const std::shared_ptr<Buffer>& buffer) : + workload_(workload), + buffer_(buffer) {} void operator()(); //thread entry private: void doWork(); - //---------------------- Shared Data ------------------------- - typedef BasicString FileName; - - struct SharedData - { - std::vector<FileName> workload; //processes last elements of vector first! - boost::mutex mutex; - boost::condition_variable condition; //signal event: data for processing available - } shared; - //------------------------------------------------------------ - - Buffer& iconBuffer; - - boost::thread threadObj; + std::shared_ptr<WorkLoad> workload_; + std::shared_ptr<Buffer> buffer_; }; -void WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new workload of icons to be retrieved -{ - { - boost::lock_guard<boost::mutex> dummy(shared.mutex); - - shared.workload.clear(); - for (std::vector<Zstring>::const_iterator i = load.begin(); i != load.end(); ++i) - shared.workload.push_back(FileName(i->c_str(), i->size())); //make DEEP COPY from Zstring - } - - shared.condition.notify_one(); - //condition handling, see: http://www.boost.org/doc/libs/1_43_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref -} - - void WorkerThread::operator()() //thread entry { //failure to initialize COM for each thread is a source of hard to reproduce bugs: https://sourceforge.net/tracker/?func=detail&aid=3160472&group_id=234430&atid=1093080 @@ -430,9 +387,9 @@ void WorkerThread::operator()() //thread entry while (true) { { - boost::unique_lock<boost::mutex> dummy(shared.mutex); - while(shared.workload.empty()) - shared.condition.wait(dummy); //interruption point! + boost::unique_lock<boost::mutex> dummy(workload_->mutex); + while(workload_->filesToLoad.empty()) + workload_->condition.wait(dummy); //interruption point! //shared.condition.timed_wait(dummy, boost::get_system_time() + boost::posix_time::milliseconds(100)); } @@ -461,14 +418,14 @@ void WorkerThread::doWork() { BasicString fileName; { - boost::lock_guard<boost::mutex> dummy(shared.mutex); - if (shared.workload.empty()) + boost::lock_guard<boost::mutex> dummy(workload_->mutex); + if (workload_->filesToLoad.empty()) break; //enter waiting state - fileName = shared.workload.back(); //deep copy - shared.workload.pop_back(); + fileName = workload_->filesToLoad.back(); //deep copy + workload_->filesToLoad.pop_back(); } - if (iconBuffer.requestFileIcon(fileName.c_str())) //thread safety: Zstring okay, won't be reference-counted in requestIcon() + if (requestFileIcon(*buffer_, Zstring(fileName))) //thread safety: Zstring okay, won't be reference-counted in requestIcon() continue; //icon already in buffer: skip #ifdef FFS_WIN @@ -476,16 +433,16 @@ void WorkerThread::doWork() if (isPriceyExtension(extension)) //"pricey" extensions are stored with fullnames and are read from disk, while cheap ones require just the extension { const IconHolder newIcon = getAssociatedIcon(fileName); - iconBuffer.insertIntoBuffer(fileName, newIcon); + insertIntoBuffer(*buffer_, fileName, newIcon); } else //no read-access to disk! determine icon by extension { const IconHolder newIcon = getAssociatedIconByExt(extension); - iconBuffer.insertIntoBuffer(extension, newIcon); + insertIntoBuffer(*buffer_, extension, newIcon); } #elif defined FFS_LINUX const IconHolder newIcon = getAssociatedIcon(fileName); - iconBuffer.insertIntoBuffer(fileName, newIcon); + insertIntoBuffer(*buffer_, fileName, newIcon); #endif } } @@ -495,16 +452,30 @@ void WorkerThread::doWork() struct IconBuffer::Pimpl { - Pimpl() : buffer(), worker(buffer) {} //might throw exceptions! + Pimpl() : + workload(std::make_shared<WorkLoad>()), + buffer(std::make_shared<Buffer>()) {} + + + std::shared_ptr<WorkLoad> workload; + std::shared_ptr<Buffer> buffer; - Buffer buffer; - WorkerThread worker; + boost::thread worker; }; -IconBuffer::IconBuffer() : pimpl(new Pimpl) {} +IconBuffer::IconBuffer() : pimpl(new Pimpl) +{ + pimpl->worker = boost::thread(WorkerThread(pimpl->workload, pimpl->buffer)); +} + -IconBuffer::~IconBuffer() {} //auto_ptr<>: keep destructor non-inline +IconBuffer::~IconBuffer() +{ + setWorkload(std::vector<Zstring>()); //make sure interruption point is always reached! + pimpl->worker.interrupt(); + pimpl->worker.join(); +} const wxIcon& IconBuffer::getDirectoryIcon() { return ::getDirectoryIcon(); } @@ -516,6 +487,19 @@ IconBuffer& IconBuffer::getInstance() return instance; } -bool IconBuffer::requestFileIcon(const Zstring& fileName, wxIcon* icon) { return pimpl->buffer.requestFileIcon(fileName, icon); } +bool IconBuffer::requestFileIcon(const Zstring& fileName, wxIcon* icon) { return ::requestFileIcon(*pimpl->buffer, fileName, icon); } + +void IconBuffer::setWorkload(const std::vector<Zstring>& load) +{ + { + boost::lock_guard<boost::mutex> dummy(pimpl->workload->mutex); -void IconBuffer::setWorkload(const std::vector<Zstring>& load) { return pimpl->worker.setWorkload(load); } + pimpl->workload->filesToLoad.clear(); + + std::transform(load.begin(), load.end(), std::back_inserter(pimpl->workload->filesToLoad), + [](const Zstring& file) { return BasicString(file); }); //make DEEP COPY from Zstring + } + + pimpl->workload->condition.notify_one(); + //condition handling, see: http://www.boost.org/doc/libs/1_43_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref +} diff --git a/library/icon_buffer.h b/library/icon_buffer.h index 5ab2740c..87f0cd4a 100644 --- a/library/icon_buffer.h +++ b/library/icon_buffer.h @@ -17,7 +17,7 @@ namespace zen class IconBuffer { public: - static const wxIcon& getDirectoryIcon(); //one icon should be sufficient... + static const wxIcon& getDirectoryIcon(); //generic icons static const wxIcon& getFileIcon(); // static IconBuffer& getInstance(); @@ -35,7 +35,7 @@ private: ~IconBuffer(); struct Pimpl; - std::auto_ptr<Pimpl> pimpl; + std::unique_ptr<Pimpl> pimpl; }; } diff --git a/library/lock_holder.h b/library/lock_holder.h index 38323695..dc88ce71 100644 --- a/library/lock_holder.h +++ b/library/lock_holder.h @@ -8,7 +8,7 @@ namespace zen { -const Zstring LOCK_FILE_ENDING = Zstr("ffs_lock"); //intermediate locks created by DirLock use this extension, too! +const Zstring LOCK_FILE_ENDING = Zstr(".ffs_lock"); //intermediate locks created by DirLock use this extension, too! //convenience class for creating and holding locks for a number of directories class LockHolder @@ -18,21 +18,21 @@ public: { if (dirnameFmt.empty()) return; if (lockHolder.find(dirnameFmt) != lockHolder.end()) return; - assert(dirnameFmt.EndsWith(common::FILE_NAME_SEPARATOR)); //this is really the contract, formatting does other things as well, e.g. macro substitution + assert(dirnameFmt.EndsWith(FILE_NAME_SEPARATOR)); //this is really the contract, formatting does other things as well, e.g. macro substitution class WaitOnLockHandler : public DirLockCallback { public: WaitOnLockHandler(ProcessCallback& pc) : pc_(pc) {} virtual void requestUiRefresh() { pc_.requestUiRefresh(); } //allowed to throw exceptions - virtual void reportInfo(const Zstring& text) { pc_.reportInfo(text); } + virtual void reportInfo(const std::wstring& text) { pc_.reportInfo(text); } private: ProcessCallback& pc_; } callback(procCallback); try { - lockHolder.insert(std::make_pair(dirnameFmt, DirLock(dirnameFmt + Zstr("sync.") + LOCK_FILE_ENDING, &callback))); + lockHolder.insert(std::make_pair(dirnameFmt, DirLock(dirnameFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback))); } catch (const FileError& e) { diff --git a/library/process_xml.cpp b/library/process_xml.cpp index 1b5f6360..69dad7f3 100644 --- a/library/process_xml.cpp +++ b/library/process_xml.cpp @@ -88,6 +88,7 @@ void xmlAccess::OptionalDialogs::resetDialogs() warningNotEnoughDiskSpace = true; warningUnresolvedConflicts = true; warningSyncDatabase = true; + warningRecyclerMissing = true; popupOnConfigChange = true; showSummaryBeforeSync = true; } @@ -747,6 +748,7 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inOpt["CheckForFreeDiskSpace"](config.optDialogs.warningNotEnoughDiskSpace); inOpt["CheckForUnresolvedConflicts"](config.optDialogs.warningUnresolvedConflicts); inOpt["NotifyDatabaseError"](config.optDialogs.warningSyncDatabase); + inOpt["CheckMissingRecycleBin"](config.optDialogs.warningRecyclerMissing); inOpt["PopupOnConfigChange"](config.optDialogs.popupOnConfigChange); inOpt["SummaryBeforeSync" ](config.optDialogs.showSummaryBeforeSync); @@ -761,6 +763,8 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inWnd["PosY" ](config.gui.dlgPos.y); inWnd["Maximized"](config.gui.isMaximized); + inWnd["MaxFolderPairsVisible"](config.gui.maxFolderPairsVisible); + inWnd["ManualDeletionOnBothSides"](config.gui.deleteOnBothSides); inWnd["ManualDeletionUseRecycler"](config.gui.useRecyclerForManualDeletion); inWnd["RespectCaseOnSearch" ](config.gui.textSearchRespectCase); @@ -796,10 +800,8 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inGui["ExternalApplications"](config.gui.externelApplications); //load config file history - XmlIn inHist = inGui["ConfigHistory"]; - - inHist.attribute("LastUsed", config.gui.lastUsedConfigFile); - inHist(config.gui.cfgFileHistory); + inGui["LastConfigActive"](config.gui.lastUsedConfigFiles); + inGui["ConfigHistory"](config.gui.cfgFileHistory); //last update check inGui["LastUpdateCheck"](config.gui.lastUpdateCheck); @@ -812,7 +814,7 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) template <class ConfigType> void readConfig(const wxString& filename, XmlType type, ConfigType& config) { - if (!fileExists(wxToZ(filename))) + if (!fileExists(toZ(filename))) throw FfsXmlError(wxString(_("File does not exist:")) + wxT("\n\"") + filename + wxT("\"")); XmlDoc doc; @@ -1003,6 +1005,7 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outOpt["CheckForFreeDiskSpace"](config.optDialogs.warningNotEnoughDiskSpace); outOpt["CheckForUnresolvedConflicts"](config.optDialogs.warningUnresolvedConflicts); outOpt["NotifyDatabaseError"](config.optDialogs.warningSyncDatabase); + outOpt["CheckMissingRecycleBin"](config.optDialogs.warningRecyclerMissing); outOpt["PopupOnConfigChange"](config.optDialogs.popupOnConfigChange); outOpt["SummaryBeforeSync" ](config.optDialogs.showSummaryBeforeSync); @@ -1017,6 +1020,8 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outWnd["PosY" ](config.gui.dlgPos.y); outWnd["Maximized"](config.gui.isMaximized); + outWnd["MaxFolderPairsVisible"](config.gui.maxFolderPairsVisible); + outWnd["ManualDeletionOnBothSides"](config.gui.deleteOnBothSides); outWnd["ManualDeletionUseRecycler"](config.gui.useRecyclerForManualDeletion); outWnd["RespectCaseOnSearch" ](config.gui.textSearchRespectCase); @@ -1048,10 +1053,8 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outGui["ExternalApplications"](config.gui.externelApplications); //load config file history - XmlOut outHist = outGui["ConfigHistory"]; - - outHist.attribute("LastUsed", config.gui.lastUsedConfigFile); - outHist(config.gui.cfgFileHistory); + outGui["LastConfigActive"](config.gui.lastUsedConfigFiles); + outGui["ConfigHistory"](config.gui.cfgFileHistory); //last update check outGui["LastUpdateCheck"](config.gui.lastUpdateCheck); diff --git a/library/process_xml.h b/library/process_xml.h index 2e57c433..d7437825 100644 --- a/library/process_xml.h +++ b/library/process_xml.h @@ -125,6 +125,7 @@ struct OptionalDialogs bool warningNotEnoughDiskSpace; bool warningUnresolvedConflicts; bool warningSyncDatabase; + bool warningRecyclerMissing; bool popupOnConfigChange; bool showSummaryBeforeSync; }; @@ -159,6 +160,7 @@ struct XmlGlobalSettings dlgPos(wxDefaultCoord, wxDefaultCoord), dlgSize(wxDefaultCoord, wxDefaultCoord), isMaximized(false), + maxFolderPairsVisible(6), autoAdjustColumnsLeft(false), autoAdjustColumnsRight(false), folderHistMax(12), @@ -191,6 +193,8 @@ struct XmlGlobalSettings wxSize dlgSize; bool isMaximized; + int maxFolderPairsVisible; + ColumnAttributes columnAttribLeft; ColumnAttributes columnAttribRight; @@ -200,7 +204,7 @@ struct XmlGlobalSettings ExternalApps externelApplications; std::vector<wxString> cfgFileHistory; - wxString lastUsedConfigFile; + std::vector<wxString> lastUsedConfigFiles; std::vector<wxString> folderHistoryLeft; std::vector<wxString> folderHistoryRight; diff --git a/library/resources.cpp b/library/resources.cpp index abdfdf51..179033a7 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -11,7 +11,6 @@ #include <wx/icon.h> #include <wx/mstream.h> #include "../shared/string_conv.h" -#include "../shared/system_constants.h" #include <memory> #include "../shared/standard_paths.h" @@ -102,9 +101,6 @@ void GlobalResources::load() //for compatibility it seems we need to stick with a "real" icon *programIcon = wxIcon(wxT("A_PROGRAM_ICON")); #else - //#include "FreeFileSync.xpm" - //*programIcon = wxIcon(FreeFileSync_xpm); - //use big logo bitmap for better quality programIcon->CopyFromBitmap(getImage(wxT("FreeFileSync.png"))); #endif diff --git a/library/soft_filter.h b/library/soft_filter.h index 82ba0ba2..0a406907 100644 --- a/library/soft_filter.h +++ b/library/soft_filter.h @@ -28,22 +28,25 @@ public: size_t sizeMin, UnitSize unitSizeMin, size_t sizeMax, UnitSize unitSizeMax); - bool matchTime(zen::Int64 writeTime) const { return currentTime - writeTime <= timeSpan_; } - bool matchSize(zen::UInt64 fileSize) const { return sizeMin_ <= fileSize && fileSize <= sizeMax_; } + bool matchTime(Int64 writeTime) const { return currentTime - writeTime <= timeSpan_; } + bool matchSize(UInt64 fileSize) const { return sizeMin_ <= fileSize && fileSize <= sizeMax_; } + bool matchFolder() const { return timeSpan_ == std::numeric_limits<Int64>::max(); } + //if date filter is active we deactivate all folders: effectively gets rid of empty folders! + bool isNull() const; //filter is equivalent to NullFilter, but may be technically slower //small helper method: merge two soft filters friend SoftFilter combineFilters(const SoftFilter& first, const SoftFilter& second); private: - SoftFilter(zen::Int64 timeSpan, - zen::UInt64 sizeMin, - zen::UInt64 sizeMax); - - zen::Int64 timeSpan_; //unit: seconds - zen::UInt64 sizeMin_; //unit: bytes - zen::UInt64 sizeMax_; //unit: bytes - zen::Int64 currentTime; + SoftFilter(Int64 timeSpan, + UInt64 sizeMin, + UInt64 sizeMax); + + Int64 timeSpan_; //unit: seconds + UInt64 sizeMin_; //unit: bytes + UInt64 sizeMax_; //unit: bytes + Int64 currentTime; }; } @@ -84,18 +87,18 @@ SoftFilter::SoftFilter(size_t timeSpan, UnitTime unitTimeSpan, size_t sizeMax, UnitSize unitSizeMax) : currentTime(wxGetUTCTime()) { - zen::resolveUnits(timeSpan, unitTimeSpan, - sizeMin, unitSizeMin, - sizeMax, unitSizeMax, - timeSpan_, //unit: seconds - sizeMin_, //unit: bytes - sizeMax_); //unit: bytes + resolveUnits(timeSpan, unitTimeSpan, + sizeMin, unitSizeMin, + sizeMax, unitSizeMax, + timeSpan_, //unit: seconds + sizeMin_, //unit: bytes + sizeMax_); //unit: bytes } inline -SoftFilter::SoftFilter(zen::Int64 timeSpan, - zen::UInt64 sizeMin, - zen::UInt64 sizeMax) : +SoftFilter::SoftFilter(Int64 timeSpan, + UInt64 sizeMin, + UInt64 sizeMax) : timeSpan_(timeSpan), sizeMin_ (sizeMin), sizeMax_ (sizeMax), @@ -112,9 +115,9 @@ SoftFilter combineFilters(const SoftFilter& first, const SoftFilter& second) inline bool SoftFilter::isNull() const //filter is equivalent to NullFilter, but may be technically slower { - return timeSpan_ == std::numeric_limits<zen::Int64>::max() && + return timeSpan_ == std::numeric_limits<Int64>::max() && sizeMin_ == 0U && - sizeMax_ == std::numeric_limits<zen::UInt64>::max(); + sizeMax_ == std::numeric_limits<UInt64>::max(); } } diff --git a/library/statistics.cpp b/library/statistics.cpp index c2ba8c0c..812c869b 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -136,7 +136,6 @@ wxString Statistics::formatRemainingTime(double timeInMs) const } output.Replace(wxT("%x"), zen::toStringSep(formattedTime)); return output; - //+ wxT("(") + common::numberToWxString(common::round(timeInMs / 1000)) + wxT(")"); } @@ -227,7 +226,8 @@ wxString Statistics::getBytesPerSecond() const const double dataDelta = backRecord.second.data - frontRecord.second.data; if (!isNull(timeDelta)) - return zen::formatFilesizeToShortString(zen::UInt64(dataDelta * 1000 / timeDelta)) + _("/sec"); + if (dataDelta > 0) //may be negative if user cancels copying + return zen::formatFilesizeToShortString(zen::UInt64(dataDelta * 1000 / timeDelta)) + _("/sec"); } return wxT("-"); //fallback diff --git a/library/status_handler.h b/library/status_handler.h index c3a016d5..a7984790 100644 --- a/library/status_handler.h +++ b/library/status_handler.h @@ -8,7 +8,7 @@ #define STATUSHANDLER_H_INCLUDED #include <wx/string.h> -#include "../shared/zstring.h" +#include <string> #include "../shared/int64.h" const int UI_UPDATE_INTERVAL = 100; //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss @@ -18,21 +18,6 @@ void updateUiNow(); //do the updating //interfaces for status updates (can be implemented by GUI or Batch mode) -//overwrite virtual methods for respective functionality - -class ErrorHandler -{ -public: - ErrorHandler() {} - virtual ~ErrorHandler() {} - - enum Response - { - IGNORE_ERROR = 10, - RETRY - }; - virtual Response reportError(const Zstring& errorMessage) = 0; -}; //report status during comparison and synchronization @@ -51,21 +36,29 @@ struct ProcessCallback //these methods have to be implemented in the derived classes to handle error and status information virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID) = 0; //informs about the total amount of data that will be processed from now on - virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //called periodically after data was processed - virtual void reportInfo(const Zstring& text) = 0; + //called periodically after data was processed: expected(!) to update GUI! + virtual void reportInfo(const wxString& text) = 0; - //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events - virtual void forceUiRefresh() = 0; + //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 requestUiRefresh(bool allowExceptions = true) = 0; //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh() + //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh() + virtual void requestUiRefresh() = 0; //throw ? - virtual bool abortIsRequested() = 0; //thanks to Windows C-Api not supporting exceptions we need this one... + //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events + virtual void forceUiRefresh() = 0; //error handling: - virtual ErrorHandler::Response reportError(const wxString& errorMessage) = 0; //recoverable error situation - virtual void reportFatalError(const wxString& errorMessage) = 0; //non-recoverable error situation, implement abort! - virtual void reportWarning (const wxString& warningMessage, bool& warningActive) = 0; + enum Response + { + 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, implement abort! + virtual void reportWarning (const wxString& warningMessage, bool& warningActive) = 0; }; @@ -83,18 +76,18 @@ class StatusHandler : public ProcessCallback, public AbortCallback public: StatusHandler() : abortRequested(false) {} - virtual void requestUiRefresh(bool allowExceptions) + virtual void requestUiRefresh() { if (updateUiIsAllowed()) //test if specific time span between ui updates is over forceUiRefresh(); - if (abortRequested && allowExceptions) + if (abortRequested) abortThisProcess(); //abort can be triggered by requestAbortion() } - virtual void requestAbortion() { abortRequested = true; } //this does NOT call abortThisProcess immediately, but when appropriate (e.g. async. processes finished) - virtual bool abortIsRequested() { return abortRequested; } virtual void abortThisProcess() = 0; + virtual void requestAbortion() { abortRequested = true; } //this does NOT call abortThisProcess immediately, but when appropriate (e.g. async. processes finished) + bool abortIsRequested() { return abortRequested; } private: bool abortRequested; diff --git a/shared/assert_static.h b/shared/assert_static.h index 37705ded..9b1a189e 100644 --- a/shared/assert_static.h +++ b/shared/assert_static.h @@ -1,9 +1,10 @@ // ************************************************************************** -// * 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) * +// * This file is part of the zenXML project. It is distributed under the * +// * Boost Software License, Version 1.0. See accompanying file * +// * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. * +// * Copyright (C) 2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** -// + #ifndef ASSERTSTATIC_H_INCLUDED #define ASSERTSTATIC_H_INCLUDED diff --git a/shared/com_error.h b/shared/com_error.h index c3f7745b..909e04c1 100644 --- a/shared/com_error.h +++ b/shared/com_error.h @@ -60,7 +60,7 @@ inline std::wstring numberToHexString(long number) { wchar_t result[100]; - swprintf(result, 100, L"0x%08x", number); + ::swprintf(result, 100, L"0x%08x", number); return std::wstring(result); } diff --git a/shared/com_ptr.h b/shared/com_ptr.h index d7178fbe..fa1b3e8f 100644 --- a/shared/com_ptr.h +++ b/shared/com_ptr.h @@ -33,43 +33,49 @@ template <class T> class ComPtr { public: - ComPtr(); - ComPtr(const ComPtr& rhs); - ComPtr& operator=(const ComPtr& rhs); - ~ComPtr(); - T** init(); //get pointer for use with ::CoCreateInstance() - T* get() const; - T* release(); //throw() - void swap(ComPtr& rhs); //throw() - T* operator->() const; - -private: - T* ptr; - - struct ConversionToBool { int dummy; }; -public: - operator int ConversionToBool::* () const; //use member pointer as implicit conversion to bool (C++ Templates - Vandevoorde/Josuttis; chapter 20) -}; - - -template <class S, class T> -ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //throw() - - - - + ComPtr() : ptr(NULL) {} + ComPtr(const ComPtr& rhs) : ptr(rhs.ptr) { if (ptr) ptr->AddRef(); } + ComPtr& operator=(const ComPtr& rhs) + { + ComPtr(rhs).swap(*this); + return *this; + } + ~ComPtr() { if (ptr) ptr->Release(); } + T** init() //get pointer for use with ::CoCreateInstance() + { + ComPtr<T>().swap(*this); + return &ptr; + } + T* get() const { return ptr; } + T* release() //throw() + { + T* tmp = ptr; + ptr = NULL; + return tmp; + } + void swap(ComPtr& rhs) { std::swap(ptr, rhs.ptr); } //throw() + T* operator->() const { return ptr; } +private: + T* ptr; + struct ConversionToBool { int dummy; }; +public: + //use member pointer as implicit conversion to bool (C++ Templates - Vandevoorde/Josuttis; chapter 20) + operator int ConversionToBool::* () const { return ptr != NULL ? &ConversionToBool::dummy : NULL; } +}; +template <class S, class T> +ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //throw() @@ -79,112 +85,33 @@ ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //throw() -//################# Inline Implementation ############################# -template <class T> -inline -ComPtr<T>::ComPtr() : ptr(NULL) {} -template <class T> -inline -ComPtr<T>::ComPtr(const ComPtr& rhs) : ptr(rhs.ptr) -{ - if (ptr) - ptr->AddRef(); -} -template <class T> -inline -ComPtr<T>& ComPtr<T>::operator=(const ComPtr<T>& rhs) -{ - ComPtr(rhs).swap(*this); - return *this; -} -template <class T> -inline -ComPtr<T>::~ComPtr() -{ - if (ptr) - ptr->Release(); -} -template <class T> -inline -T** ComPtr<T>::init() //get pointer for use with ::CoCreateInstance() -{ - ComPtr<T>().swap(*this); - return &ptr; -} -template <class T> -inline -T* ComPtr<T>::get() const -{ - return ptr; -} -template <class T> -inline -T* ComPtr<T>::release() //throw() -{ - T* tmp = ptr; - ptr = NULL; - return tmp; -} -template <class T> -inline -void ComPtr<T>::swap(ComPtr<T>& rhs) //throw() -{ - std::swap(ptr, rhs.ptr); -} +//################# Inline Implementation ############################# //we cannot specialize std::swap() for a class template and are not allowed to overload it => offer swap in own namespace -template <class T> -inline +template <class T> inline void swap(util::ComPtr<T>& lhs, util::ComPtr<T>& rhs) { lhs.swap(rhs); } -template <class T> -inline -T* ComPtr<T>::operator->() const -{ - return ptr; -} - - -/* -template <class T> -inline -ComPtr<T>::operator bool() const -{ - return ptr != NULL; -} -*/ - - -template <class T> -inline -ComPtr<T>::operator int ComPtr<T>::ConversionToBool::* () const -{ - return ptr != NULL ? &ConversionToBool::dummy : NULL; -} - - -template <class S, class T> -inline +template <class S, class T> inline ComPtr<S> com_dynamic_cast(const ComPtr<T>& other) //throw() { ComPtr<S> outPtr; @@ -192,7 +119,6 @@ ComPtr<S> com_dynamic_cast(const ComPtr<T>& other) //throw() other->QueryInterface(IID_PPV_ARGS(outPtr.init())); return outPtr; } - } diff --git a/shared/com_util.h b/shared/com_util.h index a396fbee..4a8c4f54 100644 --- a/shared/com_util.h +++ b/shared/com_util.h @@ -31,10 +31,10 @@ std::wstring getText(ComPtr<T> comObj, MemFun memFun); class Bstring { public: - Bstring(const std::wstring& str); - ~Bstring(); + Bstring(const std::wstring& str) { str_ = ::SysAllocStringLen(str.data(), str.length()); } //string::data() returns unmodified string potentially containing 0-values + ~Bstring() { if (str_) ::SysFreeString(str_); } - const BSTR get() const; + const BSTR get() const { return str_; } private: Bstring(const Bstring&); //not implemented @@ -127,28 +127,6 @@ std::wstring getText(ComPtr<T> comObj, MemFun memFun) } return text; } - - -inline -Bstring::Bstring(const std::wstring& str) -{ - str_ = ::SysAllocStringLen(str.data(), str.length()); //string::data() returns unmodified string potentially containing 0-values -} - - -inline -Bstring::~Bstring() -{ - if (str_) - ::SysFreeString(str_); -} - - -inline -const BSTR Bstring::get() const -{ - return str_; -} } diff --git a/shared/custom_button.cpp b/shared/custom_button.cpp index df65a401..98c0a3cd 100644 --- a/shared/custom_button.cpp +++ b/shared/custom_button.cpp @@ -12,6 +12,44 @@ #include <cmath> +namespace +{ +bool isEqual(const wxBitmap& lhs, const wxBitmap& rhs) +{ + if (lhs.IsOk() != rhs.IsOk()) + return false; + + if (!lhs.IsOk()) + return true; + + const int pixelCount = lhs.GetWidth() * lhs.GetHeight(); + if (pixelCount != rhs.GetWidth() * rhs.GetHeight()) + return false; + + wxImage imLhs = lhs.ConvertToImage(); + wxImage imRhs = rhs.ConvertToImage(); + + if (imLhs.HasAlpha() != imRhs.HasAlpha()) + return false; + + if (imLhs.HasAlpha()) + { + if (!std::equal(imLhs.GetAlpha(), imLhs.GetAlpha() + pixelCount, imRhs.GetAlpha())) + return false; + } + + return std::equal(imLhs.GetData(), imLhs.GetData() + pixelCount * 3, imRhs.GetData()); +} +} + + +void setBitmapLabel(wxBitmapButton& button, const wxBitmap& bmp) +{ + if (!isEqual(button.GetBitmapLabel(), bmp)) + button.SetBitmapLabel(bmp); +} + + wxButtonWithImage::wxButtonWithImage(wxWindow* parent, wxWindowID id, const wxString& label, @@ -30,25 +68,34 @@ wxButtonWithImage::wxButtonWithImage(wxWindow* parent, void wxButtonWithImage::setBitmapFront(const wxBitmap& bitmap, unsigned spaceAfter) { - bitmapFront = bitmap; - m_spaceAfter = spaceAfter; - refreshButtonLabel(); + if (!isEqual(bitmap, bitmapFront) || spaceAfter != m_spaceAfter) //avoid flicker + { + bitmapFront = bitmap; + m_spaceAfter = spaceAfter; + refreshButtonLabel(); + } } void wxButtonWithImage::setTextLabel(const wxString& text) { - textLabel = text; - wxBitmapButton::SetLabel(text); - refreshButtonLabel(); + if (text != textLabel) //avoid flicker + { + textLabel = text; + wxBitmapButton::SetLabel(text); + refreshButtonLabel(); + } } void wxButtonWithImage::setBitmapBack(const wxBitmap& bitmap, unsigned spaceBefore) { - bitmapBack = bitmap; - m_spaceBefore = spaceBefore; - refreshButtonLabel(); + if (!isEqual(bitmap, bitmapBack) || spaceBefore != m_spaceBefore) //avoid flicker + { + bitmapBack = bitmap; + m_spaceBefore = spaceBefore; + refreshButtonLabel(); + } } @@ -293,19 +340,33 @@ void writeToImage(const wxImage& source, const wxPoint pos, wxImage& target) } +namespace +{ +inline +wxSize getSize(const wxBitmap& bmp) +{ + return bmp.IsOk() ? wxSize(bmp.GetWidth(), bmp.GetHeight()) : wxSize(0, 0); +} +} + + void wxButtonWithImage::refreshButtonLabel() { wxBitmap bitmapText = createBitmapFromText(textLabel); + wxSize szFront = getSize(bitmapFront); // + wxSize szText = getSize(bitmapText); //make sure to NOT access null-bitmaps! + wxSize szBack = getSize(bitmapBack); // + //calculate dimensions of new button - const int height = std::max(std::max(bitmapFront.GetHeight(), bitmapText.GetHeight()), bitmapBack.GetHeight()); - const int width = bitmapFront.GetWidth() + m_spaceAfter + bitmapText.GetWidth() + m_spaceBefore + bitmapBack.GetWidth(); + const int height = std::max(std::max(szFront.GetHeight(), szText.GetHeight()), szBack.GetHeight()); + const int width = szFront.GetWidth() + m_spaceAfter + szText.GetWidth() + m_spaceBefore + szBack.GetWidth(); //create a transparent image wxImage transparentImage(width, height, false); transparentImage.SetAlpha(); unsigned char* alpha = transparentImage.GetAlpha(); - memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, width * height); + ::memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, width * height); //wxDC::DrawLabel() unfortunately isn't working for transparent images on Linux, so we need to use custom image-concatenation if (bitmapFront.IsOk()) @@ -315,12 +376,12 @@ void wxButtonWithImage::refreshButtonLabel() if (bitmapText.IsOk()) writeToImage(bitmapText.ConvertToImage(), - wxPoint(bitmapFront.GetWidth() + m_spaceAfter, (transparentImage.GetHeight() - bitmapText.GetHeight()) / 2), + wxPoint(szFront.GetWidth() + m_spaceAfter, (transparentImage.GetHeight() - bitmapText.GetHeight()) / 2), transparentImage); if (bitmapBack.IsOk()) writeToImage(bitmapBack.ConvertToImage(), - wxPoint(bitmapFront.GetWidth() + m_spaceAfter + bitmapText.GetWidth() + m_spaceBefore, (transparentImage.GetHeight() - bitmapBack.GetHeight()) / 2), + wxPoint(szFront.GetWidth() + m_spaceAfter + szText.GetWidth() + m_spaceBefore, (transparentImage.GetHeight() - bitmapBack.GetHeight()) / 2), transparentImage); //adjust button size diff --git a/shared/custom_button.h b/shared/custom_button.h index 4ebff73c..752c763e 100644 --- a/shared/custom_button.h +++ b/shared/custom_button.h @@ -38,5 +38,8 @@ private: wxBitmap bitmapBack; }; +//set bitmap label flicker free! +void setBitmapLabel(wxBitmapButton& button, const wxBitmap& bmp); + #endif // CUSTOMBUTTON_H_INCLUDED diff --git a/shared/debug_log.h b/shared/debug_log.h new file mode 100644 index 00000000..8e8090f0 --- /dev/null +++ b/shared/debug_log.h @@ -0,0 +1,80 @@ +// ************************************************************************** +// * 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 DEBUG_LOG_HEADER_017324601673246392184621895740256342 +#define DEBUG_LOG_HEADER_017324601673246392184621895740256342 + +#include "zstring.h" +#include <wx/file.h> + + +class DebugLog +{ +public: + wxDEPRECATED(DebugLog(const wxString& filePrefix = wxString())) + prefix(filePrefix), + lineCount(0) + { + logfileName = assembleFileName(); + logFile.Open(logfileName, wxFile::write); + } + + void write(const std::string& logText) + { + todo; + } + + void write(const wxString& logText) + { + ++lineCount; + if (lineCount % 50000 == 0) //prevent logfile from becoming too big + { + logFile.Close(); + wxRemoveFile(logfileName); + + logfileName = assembleFileName(); + logFile.Open(logfileName, wxFile::write); + } + +ersetze wxDateTime::Now() durch eigene lib: + z.b. iso_time.h + + logFile.Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); + logFile.Write(logText + LINE_BREAK); + } + +private: + wxString assembleFileName() + { + wxString tmp = wxDateTime::Now().FormatISOTime(); + tmp.Replace(wxT(":"), wxEmptyString); + return prefix + wxString(wxT("DEBUG_")) + wxDateTime::Now().FormatISODate() + wxChar('_') + tmp + wxT(".log"); + } + + wxString logfileName; + wxString prefix; + int lineCount; + wxFile logFile; //logFile.close(); <- not needed +}; + +inline DebugLog& globalLogFile() +{ + static DebugLog inst; //external linkage despite header definition! + return inst; +} + +inline wxString getCodeLocation(const wxString& file, int line) +{ + return wxString(file).AfterLast(FILE_NAME_SEPARATOR) + wxT(", LINE ") + toString<wxString>(line) + wxT(" | "); +} + + +//small macro for writing debug information into a logfile +#define WRITE_DEBUG_LOG(x) globalLogFile().write(getCodeLocation(__TFILE__, __LINE__) + x); +//speed alternative: wxLogDebug(wxT("text")) + DebugView + + +#endif //DEBUG_LOG_HEADER_017324601673246392184621895740256342 diff --git a/shared/dir_name.cpp b/shared/dir_name.cpp index dda9407e..6566bb3a 100644 --- a/shared/dir_name.cpp +++ b/shared/dir_name.cpp @@ -15,7 +15,6 @@ #include "check_exist.h" #include "util.h" #include "i18n.h" -#include "system_constants.h" using namespace zen; @@ -24,7 +23,7 @@ namespace { void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, wxWindow& tooltipWnd, wxStaticBoxSizer* staticBox, size_t timeout) { - const wxString dirFormatted = zToWx(getFormattedDirectoryName(wxToZ(dirname))); + const wxString dirFormatted = toWx(getFormattedDirectoryName(toZ(dirname))); tooltipWnd.SetToolTip(dirFormatted); //wxComboBox bug: the edit control is not updated... hope this will be fixed: http://trac.wxwidgets.org/ticket/12659 @@ -32,17 +31,16 @@ void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, w { //change static box label only if there is a real difference to what is shown in wxTextCtrl anyway wxString dirNormalized = dirname; - dirNormalized.Trim(true); - dirNormalized.Trim(false); - if (!dirNormalized.empty() && !dirNormalized.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) - dirNormalized += zToWx(common::FILE_NAME_SEPARATOR); + trim(dirNormalized); + if (!dirNormalized.empty() && !endsWith(dirNormalized, FILE_NAME_SEPARATOR)) + dirNormalized += FILE_NAME_SEPARATOR; staticBox->GetStaticBox()->SetLabel(dirNormalized == dirFormatted ? wxString(_("Drag && drop")) : dirFormatted); } if (dirPicker) { - if (!dirFormatted.empty() && util::dirExists(wxToZ(dirFormatted), timeout) == util::EXISTING_TRUE) //potentially slow network access: wait 200ms at most + if (!dirFormatted.empty() && util::dirExists(toZ(dirFormatted), timeout) == util::EXISTING_TRUE) //potentially slow network access: wait 200ms at most dirPicker->SetPath(dirFormatted); } } @@ -113,14 +111,14 @@ void DirectoryNameMainDlg::OnFilesDropped(FFSFileDropEvent& event) if (AcceptDrop(event.getFiles())) { - Zstring fileName = wxToZ(event.getFiles()[0]); - if (dirExists(fileName)) - setDirectoryName(zToWx(fileName), &dirName_, &dirPicker_, dirName_, staticBox_); + wxString fileName = event.getFiles()[0]; + if (dirExists(toZ(fileName))) + setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_); else { - fileName = fileName.BeforeLast(common::FILE_NAME_SEPARATOR); - if (dirExists(fileName)) - setDirectoryName(zToWx(fileName), &dirName_, &dirPicker_, dirName_, staticBox_); + fileName = beforeLast(fileName, FILE_NAME_SEPARATOR); + if (dirExists(toZ(fileName))) + setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_); } } } @@ -183,14 +181,14 @@ void DirectoryName::OnFilesDropped(FFSFileDropEvent& event) if (event.getFiles().empty()) return; - Zstring fileName = wxToZ(event.getFiles()[0]); - if (dirExists(fileName)) - setDirectoryName(zToWx(fileName), &dirName_, &dirPicker_, dirName_, staticBox_); + wxString fileName = event.getFiles()[0]; + if (dirExists(toZ(fileName))) + setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_); else { - fileName = fileName.BeforeLast(common::FILE_NAME_SEPARATOR); - if (dirExists(fileName)) - setDirectoryName(zToWx(fileName), &dirName_, &dirPicker_, dirName_, staticBox_); + fileName = beforeLast(fileName, FILE_NAME_SEPARATOR); + if (dirExists(toZ(fileName))) + setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_); } } diff --git a/shared/dir_watcher.cpp b/shared/dir_watcher.cpp new file mode 100644 index 00000000..8e0b7f94 --- /dev/null +++ b/shared/dir_watcher.cpp @@ -0,0 +1,471 @@ +// ************************************************************************** +// * 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 "dir_watcher.h" +#include "last_error.h" +#include "i18n.h" +#include <algorithm> +#include "boost_thread_wrap.h" //include <boost/thread.hpp> +#include "loki/ScopeGuard.h" +#include <set> +#include <wx/log.h> //wxSafeShowMessage + +#ifdef FFS_WIN +#include "notify_removal.h" +#include <wx/msw/wrapwin.h> //includes "windows.h" +#include "long_path_prefix.h" +#include "privilege.h" + +#elif defined FFS_LINUX +#include <sys/inotify.h> +#include <fcntl.h> +#include "file_traverser.h" +#endif + + +using namespace zen; + + +#ifdef FFS_WIN +namespace +{ +typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class for file names +typedef Zbase<wchar_t, StorageDeepCopy> BasicWString; //thread safe string class for UI texts + + +struct SharedData +{ + boost::mutex lockAccess; + std::set<BasicString> changedFiles; //get rid of duplicate entries (actually occur!) + BasicWString errorMsg; //non-empty if errors occured in thread +}; + + +void addChanges(SharedData& shared, const char* buffer, DWORD bytesWritten, const BasicString& dirname) //throw () +{ + boost::lock_guard<boost::mutex> dummy(shared.lockAccess); + + std::set<BasicString>& output = shared.changedFiles; + + if (bytesWritten == 0) //according to docu this may happen in case of internal buffer overflow: report some "dummy" change + output.insert(L"Overflow!"); + else + { + const char* bufPos = &buffer[0]; + while (true) + { + const FILE_NOTIFY_INFORMATION& notifyInfo = reinterpret_cast<const FILE_NOTIFY_INFORMATION&>(*bufPos); + + const BasicString fullname = dirname + BasicString(notifyInfo.FileName, notifyInfo.FileNameLength / sizeof(WCHAR)); + + //skip modifications sent by changed directories: reason for change, child element creation/deletion, will notify separately! + bool skip = false; + if (notifyInfo.Action == FILE_ACTION_MODIFIED) + { + //note: this check will not work if top watched directory has been renamed + const DWORD ret = ::GetFileAttributes(applyLongPathPrefix(Zstring(fullname)).c_str()); + bool isDir = ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_DIRECTORY); //returns true for (dir-)symlinks also + skip = isDir; + } + + if (!skip) + output.insert(fullname); + + if (notifyInfo.NextEntryOffset == 0) + break; + bufPos += notifyInfo.NextEntryOffset; + } + } +} + + +void getChanges(SharedData& shared, std::vector<Zstring>& output) //throw FileError +{ + boost::lock_guard<boost::mutex> dummy(shared.lockAccess); + + //first check whether errors occured in thread + if (!shared.errorMsg.empty()) + throw zen::FileError(shared.errorMsg.c_str()); + + std::transform(shared.changedFiles.begin(), shared.changedFiles.end(), + std::back_inserter(output), [](const BasicString& str) { return Zstring(str); }); + + shared.changedFiles.clear(); +} + + +void reportError(SharedData& shared, const BasicWString& errorMsg) //throw () +{ + boost::lock_guard<boost::mutex> dummy(shared.lockAccess); + shared.errorMsg = errorMsg; +} + + +class ReadChangesAsync +{ +public: + ReadChangesAsync(const BasicString& directory, //make sure to not leak in thread-unsafe types! + const std::shared_ptr<SharedData>& shared) : + shared_(shared), + dirname(directory) + { + //still in main thread + if (!endsWith(dirname, FILE_NAME_SEPARATOR)) + dirname += FILE_NAME_SEPARATOR; + + //these two privileges are required by ::CreateFile FILE_FLAG_BACKUP_SEMANTICS according to + //http://msdn.microsoft.com/en-us/library/aa363858(v=vs.85).aspx + try + { + Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError + Privileges::getInstance().ensureActive(SE_RESTORE_NAME); // + } + catch (const FileError&) {} + + hDir = ::CreateFile(applyLongPathPrefix(dirname.c_str()).c_str(), + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, + NULL); + if(hDir == INVALID_HANDLE_VALUE ) + throw FileError(_("Could not initialize directory monitoring:") + "\n\"" + utf8CvrtTo<std::wstring>(dirname) + "\"" + "\n\n" + zen::getLastErrorFormatted()); + + //Loki::ScopeGuard guardDir = Loki::MakeGuard(::CloseHandle, hDir); + //guardDir.Dismiss(); + } + + ~ReadChangesAsync() + { + if (hDir != INVALID_HANDLE_VALUE) + ::CloseHandle(hDir); + } + + void operator()() //thread entry + { + try + { + std::vector<char> buffer(64 * 1024); //maximum buffer size restricted by some networks protocols (according to docu) + + while (true) + { + boost::this_thread::interruption_point(); + + //actual work + OVERLAPPED overlapped = {}; + overlapped.hEvent = ::CreateEvent(NULL, //__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes, + true, //__in BOOL bManualReset, + false, //__in BOOL bInitialState, + NULL); //__in_opt LPCTSTR lpName + if (overlapped.hEvent == NULL) + return ::reportError(*shared_, BasicWString(_("Error when monitoring directories.") + "\n\n" + getLastErrorFormatted())); //throw () + quit thread + + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, overlapped.hEvent); + (void)dummy; + + //asynchronous variant: runs on this thread's APC queue! + if (!::ReadDirectoryChangesW(hDir, // __in HANDLE hDirectory, + &buffer[0], // __out LPVOID lpBuffer, + static_cast<DWORD>(buffer.size()), // __in DWORD nBufferLength, + true, // __in BOOL bWatchSubtree, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE, // __in DWORD dwNotifyFilter, + NULL, // __out_opt LPDWORD lpBytesReturned, + &overlapped, // __inout_opt LPOVERLAPPED lpOverlapped, + NULL)) // __in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine + return ::reportError(*shared_, BasicWString(_("Error when monitoring directories.") + "\n\n" + getLastErrorFormatted())); //throw () + quit thread + + //async I/O is a resource that needs to be guarded since it will write to local variable "buffer"! + Loki::ScopeGuard lockAio = Loki::MakeGuard([&]() + { + //http://msdn.microsoft.com/en-us/library/aa363789(v=vs.85).aspx + bool cancelSuccess = ::CancelIo(hDir) == TRUE; //cancel all async I/O related to this handle and thread + if (cancelSuccess) + { + DWORD bytesWritten = 0; + ::GetOverlappedResult(hDir, &overlapped, &bytesWritten, true); //wait until cancellation is complete + } + }); + + DWORD bytesWritten = 0; + + //wait for results + while (!::GetOverlappedResult(hDir, //__in HANDLE hFile, + &overlapped, //__in LPOVERLAPPED lpOverlapped, + &bytesWritten, //__out LPDWORD lpNumberOfBytesTransferred, + false)) //__in BOOL bWait + { + if (::GetLastError() != ERROR_IO_INCOMPLETE) + return ::reportError(*shared_, BasicWString(_("Error when monitoring directories.") + "\n\n" + getLastErrorFormatted())); //throw () + quit thread + + //execute asynchronous procedure calls (APC) queued on this thread + ::SleepEx(50, // __in DWORD dwMilliseconds, + true); // __in BOOL bAlertable + + boost::this_thread::interruption_point(); + } + lockAio.Dismiss(); + + ::addChanges(*shared_, &buffer[0], bytesWritten, dirname); //throw () + } + } + catch (boost::thread_interrupted&) + { + throw; //this is the only reasonable exception! + } + catch (...) //exceptions must be catched per thread + { + wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Dir Watcher)"), wxT("Unknown exception in worker thread!")); //simple wxMessageBox won't do for threads + } + } + + ReadChangesAsync(ReadChangesAsync&& other) : + hDir(INVALID_HANDLE_VALUE) + { + shared_ = std::move(other.shared_); + dirname = std::move(other.dirname); + std::swap(hDir, other.hDir); + } + + HANDLE getDirHandle() const { return hDir; } //for reading purposes only, don't abuse (e.g. close handle)! + +private: + //shared between main and worker: + std::shared_ptr<SharedData> shared_; + //worker thread only: + BasicString dirname; //conceptually thread-only, but technically moved to thread-local storage on instance creation: -> must not use ref-copying! + HANDLE hDir; +}; + + +class HandleVolumeRemoval : public NotifyRequestDeviceRemoval +{ +public: + HandleVolumeRemoval(HANDLE hDir, + boost::thread& worker, + const std::shared_ptr<SharedData>& shared, + const BasicString& dirname) : + NotifyRequestDeviceRemoval(hDir), //throw FileError + worker_(worker), + shared_(shared), + dirname_(dirname), + removalRequested(false), + operationComplete(false) {} + + //all functions are called by main thread! + + bool requestReceived() const { return removalRequested; } + bool finished() const { return operationComplete; } + +private: + virtual void onRequestRemoval(HANDLE hnd) + { + //must release hDir immediately! + worker_.interrupt(); + worker_.join(); + //now hDir should have been released + + //report removal as change to main directory + { + boost::lock_guard<boost::mutex> dummy(shared_->lockAccess); + shared_->changedFiles.insert(dirname_); + } + + removalRequested = true; + } //don't throw! + virtual void onRemovalFinished(HANDLE hnd, bool successful) { operationComplete = true; } //throw()! + + boost::thread& worker_; + std::shared_ptr<SharedData> shared_; + BasicString dirname_; + bool removalRequested; + bool operationComplete; +}; +} + + +struct DirWatcher::Pimpl +{ + boost::thread worker; + std::shared_ptr<SharedData> shared; + + std::unique_ptr<HandleVolumeRemoval> volRemoval; +}; + + +DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError + pimpl_(new Pimpl) +{ + pimpl_->shared = std::make_shared<SharedData>(); + + ReadChangesAsync reader(BasicString(directory), pimpl_->shared); //throw FileError + pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker, pimpl_->shared, BasicString(directory))); //throw FileError + pimpl_->worker = boost::thread(std::move(reader)); +} + + +DirWatcher::~DirWatcher() +{ + pimpl_->worker.interrupt(); + //pimpl_->worker.join(); -> we don't have time to wait... will take ~50ms anyway + //caveat: exitting the app may simply kill this thread! + + //wait until device removal is confirmed, to (hopefully!) prevent locking hDir again by new watch! + if (pimpl_->volRemoval->requestReceived()) + { + const boost::system_time maxwait = boost::get_system_time() + boost::posix_time::seconds(3); //HandleVolumeRemoval::finished() not guaranteed! + + while (!pimpl_->volRemoval->finished() && boost::get_system_time() < maxwait) + boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(50)); + } +} + + +std::vector<Zstring> DirWatcher::getChanges() //throw FileError +{ + std::vector<Zstring> output; + ::getChanges(*pimpl_->shared, output); //throw FileError + return output; +} + + +#elif defined FFS_LINUX +struct DirWatcher::Pimpl +{ + int notifDescr; + std::map<int, Zstring> watchDescrs; //watch descriptor and corresponding directory name (postfixed with separator!) +}; + + +namespace +{ +class DirsOnlyTraverser : public zen::TraverseCallback +{ +public: + DirsOnlyTraverser(std::vector<Zstring>& dirs) : dirs_(dirs) {} + + virtual void onFile (const Zchar* shortName, const Zstring& fullName, const FileInfo& details) {} + virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} + virtual ReturnValDir onDir (const Zchar* shortName, const Zstring& fullName) + { + dirs_.push_back(fullName); + return ReturnValDir(Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_CONTINUE>(), *this); + } + virtual HandleError onError(const std::wstring& errorText) { throw FileError(errorText); } + +private: + std::vector<Zstring>& dirs_; +}; +} + + +DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError + pimpl_(new Pimpl) +{ + //still in main thread + Zstring dirname = directory; + if (endsWith(dirname, FILE_NAME_SEPARATOR)) + dirname.resize(dirname.size() - 1); + + //get all subdirectories + std::vector<Zstring> fullDirList; + fullDirList.push_back(dirname); + + DirsOnlyTraverser traverser(fullDirList); //throw FileError + zen::traverseFolder(dirname, false, traverser); //don't traverse into symlinks (analog to windows build) + + //init + pimpl_->notifDescr = ::inotify_init(); + if (pimpl_->notifDescr == -1) + throw FileError(_("Could not initialize directory monitoring:") + "\n\"" + dirname + "\"" + "\n\n" + getLastErrorFormatted()); + + Loki::ScopeGuard guardDescr = Loki::MakeGuard(::close, pimpl_->notifDescr); + + //set non-blocking mode + bool initSuccess = false; + int flags = ::fcntl(pimpl_->notifDescr, F_GETFL); + if (flags != -1) + initSuccess = ::fcntl(pimpl_->notifDescr, F_SETFL, flags | O_NONBLOCK) != -1; + + if (!initSuccess) + throw FileError(_("Could not initialize directory monitoring:") + "\n\"" + dirname + "\"" + "\n\n" + getLastErrorFormatted()); + + //add watches + std::for_each(fullDirList.begin(), fullDirList.end(), + [&](Zstring subdir) + { + int wd = ::inotify_add_watch(pimpl_->notifDescr, subdir.c_str(), + IN_ONLYDIR | //watch directories only + IN_DONT_FOLLOW | //don't follow symbolic links + IN_MODIFY | + IN_CLOSE_WRITE | + IN_MOVE | + IN_CREATE | + IN_DELETE | + IN_DELETE_SELF | + IN_MOVE_SELF); + if (wd == -1) + throw FileError(_("Could not initialize directory monitoring:") + "\n\"" + subdir + "\"" + "\n\n" + getLastErrorFormatted()); + + if (!endsWith(subdir, FILE_NAME_SEPARATOR)) + subdir += FILE_NAME_SEPARATOR; + pimpl_->watchDescrs.insert(std::make_pair(wd, subdir)); + }); + + guardDescr.Dismiss(); +} + + +DirWatcher::~DirWatcher() +{ + ::close(pimpl_->notifDescr); //associated watches are removed automatically! +} + + +std::vector<Zstring> DirWatcher::getChanges() //throw FileError +{ + std::vector<char> buffer(1024 * (sizeof(struct inotify_event) + 16)); + + //non-blocking call, see O_NONBLOCK + ssize_t bytesRead = ::read(pimpl_->notifDescr, &buffer[0], buffer.size()); + + if (bytesRead == -1) + { + if (errno == EINTR || //Interrupted function call; When this happens, you should try the call again. + errno == EAGAIN) //Non-blocking I/O has been selected using O_NONBLOCK and no data was immediately available for reading + return std::vector<Zstring>(); + + throw FileError(_("Error when monitoring directories.") + "\n\n" + getLastErrorFormatted()); + } + + std::set<Zstring> tmp; //get rid of duplicate entries (actually occur!) + + ssize_t bytePos = 0; + while (bytePos < bytesRead) + { + struct inotify_event& evt = reinterpret_cast<struct inotify_event&>(buffer[bytePos]); + + if (evt.len != 0) //exclude case: deletion of "self", already reported by parent directory watch + { + auto iter = pimpl_->watchDescrs.find(evt.wd); + if (iter != pimpl_->watchDescrs.end()) + { + //Note: evt.len is NOT the size of the evt.name c-string, but the array size including all padding 0 characters! + //It may be even 0 in which case evt.name must not be used! + tmp.insert(iter->second + evt.name); + } + } + + bytePos += sizeof(struct inotify_event) + evt.len; + } + + return std::vector<Zstring>(tmp.begin(), tmp.end()); +} + +#endif diff --git a/shared/dir_watcher.h b/shared/dir_watcher.h new file mode 100644 index 00000000..572515dc --- /dev/null +++ b/shared/dir_watcher.h @@ -0,0 +1,50 @@ +// ************************************************************************** +// * 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 DIR_WATCHER_348577025748023458 +#define DIR_WATCHER_348577025748023458 + +#include "file_error.h" +#include <vector> +#include <memory> + +namespace zen +{ +//Windows: ReadDirectoryChangesW http://msdn.microsoft.com/en-us/library/aa365465(v=vs.85).aspx +//Linux: inotify http://linux.die.net/man/7/inotify + +//watch directory including subdirectories +/* +!Note handling of directories!: + Linux: newly added subdirectories are reported but not automatically added for watching! -> reset Dirwatcher! + removal of top watched directory is NOT notified! + Windows: removal of top watched directory also NOT notified (e.g. brute force usb stick removal) + however manual unmount IS notified (e.g. usb stick removal, then re-insert), but watching is stopped! + Renaming of top watched directory handled incorrectly: Not notified(!) + changes in subfolders + report FILE_ACTION_MODIFIED for directory (check that should prevent this fails!) + + Overcome all issues portably: check existence of watched directory externally + reinstall watch after changes in directory structure (added directories) are possible +*/ +class DirWatcher +{ +public: + DirWatcher(const Zstring& directory); //throw FileError + ~DirWatcher(); + + //extract accumulated changes since last call + std::vector<Zstring> getChanges(); //throw FileError + +private: + DirWatcher(const DirWatcher&); + DirWatcher& operator=(const DirWatcher&); + + struct Pimpl; + std::unique_ptr<Pimpl> pimpl_; +}; + +} + +#endif diff --git a/shared/dll_loader.cpp b/shared/dll_loader.cpp index e942a168..029cabc5 100644 --- a/shared/dll_loader.cpp +++ b/shared/dll_loader.cpp @@ -20,20 +20,18 @@ public: HMODULE getHandle(const std::wstring& libraryName) { - HandleMap::const_iterator foundEntry = handles.find(libraryName); - if (foundEntry == handles.end()) - { - if (libraryName.empty()) - return ::GetModuleHandle(NULL); //return handle to calling executable + if (libraryName.empty()) + return ::GetModuleHandle(NULL); //return handle to calling executable - HMODULE newHandle = ::LoadLibrary(libraryName.c_str()); - if (newHandle != NULL) - handles.insert(std::make_pair(libraryName, newHandle)); + HandleMap::const_iterator iter = handles.find(libraryName); + if (iter != handles.end()) + return iter->second; - return newHandle; - } - else - return foundEntry->second; + HMODULE newHandle = ::LoadLibrary(libraryName.c_str()); + if (newHandle != NULL) + handles.insert(std::make_pair(libraryName, newHandle)); + + return newHandle; } private: @@ -56,11 +54,7 @@ private: FARPROC util::loadSymbol(const std::wstring& libraryName, const std::string& functionName) { const HMODULE libHandle = DllHandler::getInstance().getHandle(libraryName); - - if (libHandle != NULL) - return ::GetProcAddress(libHandle, functionName.c_str()); - else - return NULL; + return libHandle != NULL ? ::GetProcAddress(libHandle, functionName.c_str()) : NULL; } diff --git a/shared/dll_loader.h b/shared/dll_loader.h index 6dedc06e..3efb0d96 100644 --- a/shared/dll_loader.h +++ b/shared/dll_loader.h @@ -51,8 +51,7 @@ std::string getResourceStream(const std::wstring& libraryName, size_t resourceId //---------------Inline Implementation--------------------------------------------------- FARPROC loadSymbol(const std::wstring& libraryName, const std::string& functionName); -template <typename FunctionType> -inline +template <typename FunctionType> inline FunctionType getDllFun(const std::wstring& libraryName, const std::string& functionName) { return reinterpret_cast<FunctionType>(loadSymbol(libraryName, functionName)); diff --git a/shared/dst_hack.cpp b/shared/dst_hack.cpp index 1a2e705a..a64df448 100644 --- a/shared/dst_hack.cpp +++ b/shared/dst_hack.cpp @@ -1,5 +1,4 @@ #include "dst_hack.h" -#include "system_constants.h" #include "i18n.h" #include "long_path_prefix.h" #include "string_utf8.h" @@ -9,6 +8,7 @@ #include "global_func.h" #include <limits> #include "int64.h" +#include "file_error.h" using namespace zen; @@ -24,8 +24,8 @@ Zstring getVolumeName(const Zstring& filename) // BUFFER_SIZE)) //__in DWORD cchBufferLength // ... // Zstring volumePath = fsName; - // if (!volumePath.EndsWith(common::FILE_NAME_SEPARATOR)) //a trailing backslash is required - // volumePath += common::FILE_NAME_SEPARATOR; + // if (!volumePath.EndsWith(FILE_NAME_SEPARATOR)) //a trailing backslash is required + // volumePath += FILE_NAME_SEPARATOR; Zstring nameFmt = removeLongPathPrefix(filename); //throw() if (!nameFmt.EndsWith(Zstr("\\"))) @@ -90,11 +90,11 @@ bool dst::isFatDrive(const Zstring& fileName) //throw() namespace { -//convert zen::UInt64 and zen::Int64 to FILETIME +//convert UInt64 and Int64 to FILETIME inline -FILETIME toFiletime(zen::Int64 number) +FILETIME toFiletime(Int64 number) { - const zen::UInt64 unsig = to<zen::UInt64>(number); + const UInt64 unsig = to<UInt64>(number); FILETIME output = {}; output.dwLowDateTime = unsig.getLo(); @@ -102,7 +102,7 @@ FILETIME toFiletime(zen::Int64 number) return output; } -FILETIME toFiletime(zen::UInt64 number) +FILETIME toFiletime(UInt64 number) { FILETIME output = {}; output.dwLowDateTime = number.getLo(); @@ -111,16 +111,16 @@ FILETIME toFiletime(zen::UInt64 number) } inline -zen::UInt64 toUInt64(const FILETIME& fileTime) +UInt64 toUInt64(const FILETIME& fileTime) { - return zen::UInt64(fileTime.dwLowDateTime, fileTime.dwHighDateTime); + return UInt64(fileTime.dwLowDateTime, fileTime.dwHighDateTime); } inline -zen::Int64 toInt64(const FILETIME& fileTime) +Int64 toInt64(const FILETIME& fileTime) { - return to<zen::Int64>(zen::UInt64(fileTime.dwLowDateTime, fileTime.dwHighDateTime)); + return to<Int64>(UInt64(fileTime.dwLowDateTime, fileTime.dwHighDateTime)); } @@ -132,9 +132,9 @@ FILETIME utcToLocal(const FILETIME& utcTime) //throw (std::runtime_error) &utcTime, //__in const FILETIME *lpFileTime, &localTime)) //__out LPFILETIME lpLocalFileTime { - const wxString errorMessage = wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + wxT("(") + - wxT("High: ") + toString<wxString>(utcTime.dwHighDateTime) + wxT(" ") + - wxT("Low: ") + toString<wxString>(utcTime.dwLowDateTime) + wxT(") ") + wxT("\n\n") + zen::getLastErrorFormatted(); + const std::wstring errorMessage = _("Conversion error:") + " FILETIME -> local FILETIME: " + "(" + + "High: " + toString<std::wstring>(utcTime.dwHighDateTime) + " " + + "Low: " + toString<std::wstring>(utcTime.dwLowDateTime) + ") " + "\n\n" + getLastErrorFormatted(); throw std::runtime_error(wideToUtf8<std::string>(errorMessage)); } return localTime; @@ -149,9 +149,9 @@ FILETIME localToUtc(const FILETIME& localTime) //throw (std::runtime_error) &localTime, //__in const FILETIME *lpLocalFileTime, &utcTime)) //__out LPFILETIME lpFileTime { - const wxString errorMessage = wxString(_("Conversion error:")) + wxT(" local FILETIME -> FILETIME: ") + wxT("(") + - wxT("High: ") + toString<wxString>(localTime.dwHighDateTime) + wxT(" ") + - wxT("Low: ") + toString<wxString>(localTime.dwLowDateTime) + wxT(") ") + wxT("\n\n") + zen::getLastErrorFormatted(); + const std::wstring errorMessage = _("Conversion error:") + " local FILETIME -> FILETIME: " + "(" + + "High: " + toString<std::wstring>(localTime.dwHighDateTime) + " " + + "Low: " + toString<std::wstring>(localTime.dwLowDateTime) + ") " + "\n\n" + getLastErrorFormatted(); throw std::runtime_error(wideToUtf8<std::string>(errorMessage)); } return utcTime; @@ -181,7 +181,7 @@ const size_t WRITE_TIME_HASH_BITS = CREATE_TIME_INFO_BITS - INDICATOR_EXISTING_B template <size_t precision> -FILETIME encodeRawInformation(zen::UInt64 rawInfo) +FILETIME encodeRawInformation(UInt64 rawInfo) { rawInfo *= precision; rawInfo += toUInt64(FAT_MIN_TIME); @@ -192,13 +192,13 @@ FILETIME encodeRawInformation(zen::UInt64 rawInfo) template <size_t precision> -zen::UInt64 extractRawInformation(const FILETIME& createTime) +UInt64 extractRawInformation(const FILETIME& createTime) { assert(toUInt64(FAT_MIN_TIME) <= toUInt64(createTime)); assert(toUInt64(createTime) <= toUInt64(FAT_MAX_TIME)); //FAT create time ranges from 1980 - 2107 (2^7 years) with 1/100 seconds precision - zen::UInt64 rawInfo = toUInt64(createTime); + UInt64 rawInfo = toUInt64(createTime); rawInfo -= toUInt64(FAT_MIN_TIME); rawInfo /= precision; //reduce precision (FILETIME has unit 10^-7 s) @@ -209,9 +209,9 @@ zen::UInt64 extractRawInformation(const FILETIME& createTime) //convert write time to it's minimal representation (no restriction to FAT range "1980 - 2107") -zen::UInt64 extractRawWriteTime(const FILETIME& writeTime) +UInt64 extractRawWriteTime(const FILETIME& writeTime) { - zen::UInt64 rawInfo = toUInt64(writeTime); + UInt64 rawInfo = toUInt64(writeTime); assert(rawInfo % PRECISION_WRITE_TIME == 0U); rawInfo /= PRECISION_WRITE_TIME; //reduce precision (FILETIME has unit 10^-7 s) return rawInfo; @@ -221,7 +221,7 @@ zen::UInt64 extractRawWriteTime(const FILETIME& writeTime) //files with different resolution than 2 seconds are rounded up when written to FAT FILETIME roundToFatWriteTime(const FILETIME& writeTime) { - zen::UInt64 rawData = toUInt64(writeTime); + UInt64 rawData = toUInt64(writeTime); if (rawData % PRECISION_WRITE_TIME != 0U) rawData += PRECISION_WRITE_TIME; @@ -249,8 +249,8 @@ std::bitset<UTC_LOCAL_OFFSET_BITS> getUtcLocalShift() if (std::bitset<UTC_LOCAL_OFFSET_BITS - 1>(absValue).to_ulong() != static_cast<unsigned long>(absValue) || //time shifts that big shouldn't be possible! timeShiftSec % (60 * 15) != 0) //all known time shift have at least 15 minute granularity! { - const wxString errorMessage = wxString(_("Conversion error:")) + wxT(" Unexpected UTC <-> local time shift: ") + - wxT("(") + toString<wxString>(timeShiftSec) + wxT(") ") + wxT("\n\n") + zen::getLastErrorFormatted(); + const std::wstring errorMessage = _("Conversion error:") + " Unexpected UTC <-> local time shift: " + + "(" + toString<std::wstring>(timeShiftSec) + ") " + "\n\n" + getLastErrorFormatted(); throw std::runtime_error(wideToUtf8<std::string>(errorMessage)); } @@ -284,7 +284,7 @@ bool dst::fatHasUtcEncoded(const RawTime& rawTime) //"createTimeRaw" as retrieve return false; } - const zen::UInt64 rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); + const UInt64 rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); assert_static(WRITE_TIME_HASH_BITS == 30); return (extractRawWriteTime(utcToLocal(rawTime.writeTimeRaw)) & 0x3FFFFFFFU) == (rawInfo & 0x3FFFFFFFU) && //ensure write time wasn't changed externally @@ -299,7 +299,7 @@ dst::RawTime dst::fatEncodeUtcTime(const FILETIME& writeTimeRealUtc) //throw (st //create time lets us store 40 bit of information //indicator that utc time is encoded -> hopefully results in a date long way in the future; but even if this bit is accidentally set, we still have the hash! - zen::UInt64 data = 1U; + UInt64 data = 1U; const std::bitset<UTC_LOCAL_OFFSET_BITS> utcShift = getUtcLocalShift(); data <<= UTC_LOCAL_OFFSET_BITS; @@ -322,14 +322,14 @@ FILETIME dst::fatDecodeUtcTime(const RawTime& rawTime) //return real UTC time; t if (!fatHasUtcEncoded(rawTime)) return rawTime.writeTimeRaw; - const zen::UInt64 rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); + const UInt64 rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); - const std::bitset<UTC_LOCAL_OFFSET_BITS> rawShift(zen::to<int>((rawInfo >> WRITE_TIME_HASH_BITS) & 0x7FU)); //static_cast<int>: a shame MSC... "unsigned long" should be supported instead! + const std::bitset<UTC_LOCAL_OFFSET_BITS> rawShift(to<int>((rawInfo >> WRITE_TIME_HASH_BITS) & 0x7FU)); //static_cast<int>: a shame MSC... "unsigned long" should be supported instead! assert_static(UTC_LOCAL_OFFSET_BITS == 7); const int timeShiftSec = convertUtcLocalShift(rawShift); const FILETIME writeTimeLocal = utcToLocal(rawTime.writeTimeRaw); - const zen::Int64 realUTC = toInt64(writeTimeLocal) - zen::Int64(timeShiftSec) * 10000000; + const Int64 realUTC = toInt64(writeTimeLocal) - Int64(timeShiftSec) * 10000000; return toFiletime(realUTC); } diff --git a/shared/file_error.h b/shared/file_error.h index 7325e14b..ae9cc83e 100644 --- a/shared/file_error.h +++ b/shared/file_error.h @@ -7,7 +7,9 @@ #ifndef FILEERROR_H_INCLUDED #define FILEERROR_H_INCLUDED -#include <wx/string.h> +#include "zstring.h" +#include "string_utf8.h" +#include <string> namespace zen @@ -15,24 +17,32 @@ namespace zen class FileError //Exception base class used to notify file/directory copy/delete errors { public: - FileError(const wxString& message) : errorMessage(message) {} + FileError(const std::wstring& message) : errorMessage(message) {} virtual ~FileError() {} - const wxString& msg() const - { - return errorMessage; - } + const std::wstring& msg() const { return errorMessage; } private: - const wxString errorMessage; + std::wstring errorMessage; }; -#define DEFINE_NEW_FILE_ERROR(X) struct X : public FileError { X(const wxString& message) : FileError(message) {} }; +#define DEFINE_NEW_FILE_ERROR(X) struct X : public FileError { X(const std::wstring& message) : FileError(message) {} }; DEFINE_NEW_FILE_ERROR(ErrorNotExisting); DEFINE_NEW_FILE_ERROR(ErrorTargetExisting); DEFINE_NEW_FILE_ERROR(ErrorTargetPathMissing); DEFINE_NEW_FILE_ERROR(ErrorFileLocked); + + + +//facilitate usage of std::wstring for error messages: + +//allow implicit UTF8 conversion: since std::wstring models a GUI string, convenience is more important than performance +inline std::wstring operator+(const std::wstring& lhs, const Zstring& rhs) { return std::wstring(lhs) += zen::utf8CvrtTo<std::wstring>(rhs); } + +//we musn't put our overloads in namespace std, but namespace zen (+ using directive) is sufficient +inline std::wstring operator+(const std::wstring& lhs, const char* rhs) { return std::wstring(lhs) += utf8CvrtTo<std::wstring>(rhs); } +inline std::wstring operator+(const std::wstring& lhs, const std::string& rhs) { return std::wstring(lhs) += utf8CvrtTo<std::wstring>(rhs); } } #endif // FILEERROR_H_INCLUDED diff --git a/shared/file_handling.cpp b/shared/file_handling.cpp index a17f1fd7..a5e7fa9f 100644 --- a/shared/file_handling.cpp +++ b/shared/file_handling.cpp @@ -10,9 +10,7 @@ #include <boost/bind.hpp> #include <stdexcept> #include "last_error.h" -#include "system_constants.h" #include "file_traverser.h" -#include "string_conv.h" #include "loki/ScopeGuard.h" #include "symlink_target.h" #include "file_io.h" @@ -50,7 +48,7 @@ bool zen::fileExists(const Zstring& filename) return ret != INVALID_FILE_ATTRIBUTES && !(ret & FILE_ATTRIBUTE_DIRECTORY); //returns true for (file-)symlinks also #elif defined FFS_LINUX - struct stat fileInfo; + struct stat fileInfo = {}; return ::lstat(filename.c_str(), &fileInfo) == 0 && (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode)); //in Linux a symbolic link is neither file nor directory #endif @@ -62,10 +60,10 @@ bool zen::dirExists(const Zstring& dirname) //symbolic links (broken or not) are also treated as existing directories! #ifdef FFS_WIN const DWORD ret = ::GetFileAttributes(applyLongPathPrefix(dirname).c_str()); - return (ret != INVALID_FILE_ATTRIBUTES) && (ret & FILE_ATTRIBUTE_DIRECTORY); //returns true for (dir-)symlinks also + return ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_DIRECTORY); //returns true for (dir-)symlinks also #elif defined FFS_LINUX - struct stat dirInfo; + struct stat dirInfo = {}; return ::lstat(dirname.c_str(), &dirInfo) == 0 && (S_ISLNK(dirInfo.st_mode) || S_ISDIR(dirInfo.st_mode)); //in Linux a symbolic link is neither file nor directory #endif @@ -79,7 +77,7 @@ bool zen::symlinkExists(const Zstring& objname) return ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_REPARSE_POINT); #elif defined FFS_LINUX - struct stat fileInfo; + struct stat fileInfo = {}; return ::lstat(objname.c_str(), &fileInfo) == 0 && S_ISLNK(fileInfo.st_mode); //symbolic link #endif @@ -92,7 +90,7 @@ bool zen::somethingExists(const Zstring& objname) //throw() check whether return ::GetFileAttributes(applyLongPathPrefix(objname).c_str()) != INVALID_FILE_ATTRIBUTES; #elif defined FFS_LINUX - struct stat fileInfo; + struct stat fileInfo = {}; return ::lstat(objname.c_str(), &fileInfo) == 0; #endif } @@ -101,6 +99,64 @@ bool zen::somethingExists(const Zstring& objname) //throw() check whether #ifdef FFS_WIN namespace { +//manage file handle to update existing files (temporarily resetting read-only if necessary) +//CreateFileCmd: lambda directly returning non-owned file handle from ::CreateFile() +class FileUpdateHandle +{ +public: + template <class CreateFileCmd> + FileUpdateHandle(const Zstring& filename, CreateFileCmd cmd) : + filenameFmt(applyLongPathPrefix(filename)), + hFile(INVALID_HANDLE_VALUE), + attr(INVALID_FILE_ATTRIBUTES) + { + hFile = cmd(); + if (hFile != INVALID_HANDLE_VALUE) + return; + + const DWORD lastError = ::GetLastError(); + if (lastError == ERROR_ACCESS_DENIED) //function fails if file is read-only + { + Loki::ScopeGuard guardErrorCode = Loki::MakeGuard(::SetLastError, lastError); //transactional behavior: ensure cleanup (e.g. network drop) -> cref [!] + + //read-only file attribute may cause trouble: temporarily reset it + const DWORD tmpAttr = ::GetFileAttributes(filenameFmt.c_str()); + if (tmpAttr != INVALID_FILE_ATTRIBUTES && (tmpAttr & FILE_ATTRIBUTE_READONLY)) + { + if (::SetFileAttributes(filenameFmt.c_str(), FILE_ATTRIBUTE_NORMAL)) + { + guardErrorCode.Dismiss(); + attr = tmpAttr; //"create" guard on read-only attribute + + //now try again + hFile = cmd(); + } + } + } + } + + ~FileUpdateHandle() + { + if (hFile != INVALID_HANDLE_VALUE) + ::CloseHandle(hFile); + + if (attr != INVALID_FILE_ATTRIBUTES) + ::SetFileAttributes(filenameFmt.c_str(), attr); + } + + //may return INVALID_FILE_ATTRIBUTES, in which case ::GetLastError() may be called directly after FileUpdateHandle() + HANDLE get() const { return hFile; } + +private: + FileUpdateHandle(const FileUpdateHandle&); + FileUpdateHandle& operator=(const FileUpdateHandle&); + + Zstring filenameFmt; + HANDLE hFile; + DWORD attr; +}; + + zen::UInt64 getFileSizeSymlink(const Zstring& linkName) //throw (FileError) { //open handle to target of symbolic link @@ -112,19 +168,14 @@ zen::UInt64 getFileSizeSymlink(const Zstring& linkName) //throw (FileError) FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zen::zToWx(linkName) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + zen::getLastErrorFormatted()); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hFile); (void)dummy; //silence warning "unused variable" BY_HANDLE_FILE_INFORMATION fileInfo = {}; if (!::GetFileInformationByHandle(hFile, &fileInfo)) - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zen::zToWx(linkName) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + zen::getLastErrorFormatted()); return zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); } @@ -138,10 +189,8 @@ zen::UInt64 zen::getFilesize(const Zstring& filename) //throw (FileError) WIN32_FIND_DATA fileInfo = {}; const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(filename).c_str(), &fileInfo); if (searchHandle == INVALID_HANDLE_VALUE) - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted()); + ::FindClose(searchHandle); const bool isSymbolicLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; @@ -153,10 +202,7 @@ zen::UInt64 zen::getFilesize(const Zstring& filename) //throw (FileError) #elif defined FFS_LINUX struct stat fileInfo = {}; if (::stat(filename.c_str(), &fileInfo) != 0) //follow symbolic links - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted()); return zen::UInt64(fileInfo.st_size); #endif @@ -177,8 +223,8 @@ DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! return 0; Zstring volumePath = &buffer[0]; - if (!volumePath.EndsWith(common::FILE_NAME_SEPARATOR)) - volumePath += common::FILE_NAME_SEPARATOR; + if (!volumePath.EndsWith(FILE_NAME_SEPARATOR)) + volumePath += FILE_NAME_SEPARATOR; DWORD volumeSerial = 0; if (!::GetVolumeInformation(volumePath.c_str(), //__in_opt LPCTSTR lpRootPathName, @@ -200,13 +246,13 @@ dev_t retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! Zstring volumePathName = pathName; //remove trailing slash - if (volumePathName.size() > 1 && volumePathName.EndsWith(common::FILE_NAME_SEPARATOR)) //exception: allow '/' - volumePathName = volumePathName.BeforeLast(common::FILE_NAME_SEPARATOR); + if (volumePathName.size() > 1 && volumePathName.EndsWith(FILE_NAME_SEPARATOR)) //exception: allow '/' + volumePathName = volumePathName.BeforeLast(FILE_NAME_SEPARATOR); struct stat fileInfo = {}; while (::lstat(volumePathName.c_str(), &fileInfo) != 0) //go up in folder hierarchy until existing folder is found { - volumePathName = volumePathName.BeforeLast(common::FILE_NAME_SEPARATOR); //returns empty string if ch not found + volumePathName = volumePathName.BeforeLast(FILE_NAME_SEPARATOR); //returns empty string if ch not found if (volumePathName.empty()) return 0; //this includes path "/" also! } @@ -219,13 +265,8 @@ dev_t retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! zen::ResponseSameVol zen::onSameVolume(const Zstring& folderLeft, const Zstring& folderRight) //throw() { -#ifdef FFS_WIN - typedef DWORD VolSerial; -#elif defined FFS_LINUX - typedef dev_t VolSerial; -#endif - const VolSerial serialLeft = retrieveVolumeSerial(folderLeft); //returns 0 on error! - const VolSerial serialRight = retrieveVolumeSerial(folderRight); //returns 0 on error! + const auto serialLeft = retrieveVolumeSerial(folderLeft); //returns 0 on error! + const auto serialRight = retrieveVolumeSerial(folderRight); //returns 0 on error! if (serialLeft == 0 || serialRight == 0) return VOLUME_CANT_SAY; @@ -254,10 +295,11 @@ bool zen::removeFile(const Zstring& filename) //throw (FileError); if (::DeleteFile(filenameFmt.c_str())) return true; } -#endif //eval error code before next call - wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(); + DWORD lastError = ::GetLastError(); +#elif defined FFS_LINUX + int lastError = errno; +#endif //no error situation if file is not existing! manual deletion relies on it! //perf: place check in error handling block @@ -265,7 +307,7 @@ bool zen::removeFile(const Zstring& filename) //throw (FileError); if (!somethingExists(filename)) return false; //neither file nor any other object (e.g. broken symlink) with that name existing - throw FileError(errorMessage); + throw FileError(_("Error deleting file:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError)); } return true; } @@ -286,8 +328,6 @@ DEFINE_NEW_FILE_ERROR(ErrorDifferentVolume); //throw (FileError); ErrorDifferentVolume if it is due to moving file to another volume void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw (FileError: ErrorDifferentVolume, ErrorTargetExisting) { - using namespace zen; //for zToWx() - #ifdef FFS_WIN const Zstring oldNameFmt = applyLongPathPrefix(oldName); const Zstring newNameFmt = applyLongPathPrefix(newName); @@ -296,10 +336,11 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw newNameFmt.c_str(), //__in_opt LPCTSTR lpNewFileName, 0)) //__in DWORD dwFlags { - if (::GetLastError() == ERROR_ACCESS_DENIED) //MoveFileEx may fail to rename a read-only file on a SAMBA-share -> (try to) handle this + DWORD lastError = ::GetLastError(); + if (lastError == ERROR_ACCESS_DENIED) //MoveFileEx may fail to rename a read-only file on a SAMBA-share -> (try to) handle this { - const DWORD oldNameAttrib = ::GetFileAttributes(oldNameFmt.c_str()); - if (oldNameAttrib != INVALID_FILE_ATTRIBUTES) + const DWORD oldAttr = ::GetFileAttributes(oldNameFmt.c_str()); + if (oldAttr != INVALID_FILE_ATTRIBUTES && (oldAttr & FILE_ATTRIBUTE_READONLY)) { if (::SetFileAttributes(oldNameFmt.c_str(), FILE_ATTRIBUTE_NORMAL)) //remove readonly-attribute { @@ -309,26 +350,21 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw 0)) //__in DWORD dwFlags { //(try to) restore file attributes - ::SetFileAttributes(newNameFmt.c_str(), oldNameAttrib); //don't handle error + ::SetFileAttributes(newNameFmt.c_str(), oldAttr); //don't handle error return; } else { - Loki::ScopeGuard dummy = Loki::MakeGuard(::SetLastError, ::GetLastError()); //use error code from ::MoveFileEx() - (void)dummy; + lastError = ::GetLastError(); //use error code from second call to ::MoveFileEx() //cleanup: (try to) restore file attributes: assume oldName is still existing - ::SetFileAttributes(oldNameFmt.c_str(), - oldNameAttrib); + ::SetFileAttributes(oldNameFmt.c_str(), oldAttr); } } } } - const DWORD lastError = ::GetLastError(); - - wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(oldName) + wxT("\" ->\n\"") + zToWx(newName) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == ERROR_NOT_SAME_DEVICE) throw ErrorDifferentVolume(errorMessage); @@ -343,8 +379,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw { const int lastError = errno; - wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(oldName) + wxT("\" ->\n\"") + zToWx(newName) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == EXDEV) throw ErrorDifferentVolume(errorMessage); @@ -384,10 +419,10 @@ Zstring getFilenameFmt(const Zstring& filename, Function fun) //throw(); returns Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short name { - const Zstring pathPrefix = fileName.find(common::FILE_NAME_SEPARATOR) != Zstring::npos ? - (fileName.BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR) : Zstring(); + const Zstring pathPrefix = fileName.find(FILE_NAME_SEPARATOR) != Zstring::npos ? + (fileName.BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR) : Zstring(); - Zstring extension = fileName.AfterLast(common::FILE_NAME_SEPARATOR).AfterLast(Zchar('.')); //extension needn't contain reasonable data + Zstring extension = fileName.AfterLast(FILE_NAME_SEPARATOR).AfterLast(Zchar('.')); //extension needn't contain reasonable data if (extension.empty()) extension = Zstr("FFS"); extension.Truncate(3); @@ -399,7 +434,7 @@ Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short n return output; } - throw std::runtime_error(std::string("100000000 files, one for each number, exist in this directory? You're kidding...\n") + std::string(wxString(pathPrefix.c_str()).ToUTF8())); + throw std::runtime_error(std::string("100000000 files, one for each number, exist in this directory? You're kidding...\n") + zen::utf8CvrtTo<std::string>(pathPrefix)); } @@ -408,14 +443,14 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw { using namespace zen; - if (newName.find(common::FILE_NAME_SEPARATOR) == Zstring::npos) + if (newName.find(FILE_NAME_SEPARATOR) == Zstring::npos) return false; if (zen::somethingExists(newName)) //name OR directory! { - const Zstring fileNameOrig = newName.AfterLast(common::FILE_NAME_SEPARATOR); //returns the whole string if ch not found - const Zstring fileNameShort = getFilenameFmt(newName, ::GetShortPathName).AfterLast(common::FILE_NAME_SEPARATOR); //throw() returns empty string on error - const Zstring fileNameLong = getFilenameFmt(newName, ::GetLongPathName) .AfterLast(common::FILE_NAME_SEPARATOR); //throw() returns empty string on error + const Zstring fileNameOrig = newName.AfterLast(FILE_NAME_SEPARATOR); //returns the whole string if ch not found + const Zstring fileNameShort = getFilenameFmt(newName, ::GetShortPathName).AfterLast(FILE_NAME_SEPARATOR); //throw() returns empty string on error + const Zstring fileNameLong = getFilenameFmt(newName, ::GetLongPathName) .AfterLast(FILE_NAME_SEPARATOR); //throw() returns empty string on error if (!fileNameShort.empty() && !fileNameLong.empty() && @@ -425,8 +460,7 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw //we detected an event where newName is in shortname format (although it is intended to be a long name) and //writing target file failed because another unrelated file happens to have the same short name - const Zstring unrelatedPathLong = newName.BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + - fileNameLong; + const Zstring unrelatedPathLong = newName.BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileNameLong; //find another name in short format: this ensures the actual short name WILL be renamed as well! const Zstring parkedTarget = createTemp8Dot3Name(newName); @@ -467,8 +501,6 @@ void zen::renameFile(const Zstring& oldName, const Zstring& newName) //throw (Fi } -using zen::CallbackMoveFile; - class CopyCallbackImpl : public zen::CallbackCopyFile //callback functionality { public: @@ -476,17 +508,9 @@ public: virtual void deleteTargetFile(const Zstring& targetFile) { assert(!fileExists(targetFile)); } - virtual Response updateCopyStatus(zen::UInt64 totalBytesTransferred) + virtual void updateCopyStatus(zen::UInt64 totalBytesTransferred) { - switch (moveCallback.requestUiRefresh(sourceFile_)) - { - case CallbackMoveFile::CONTINUE: - return CallbackCopyFile::CONTINUE; - - case CallbackMoveFile::CANCEL: - return CallbackCopyFile::CANCEL; - } - return CallbackCopyFile::CONTINUE; //dummy return value + moveCallback.requestUiRefresh(sourceFile_); } private: @@ -499,20 +523,13 @@ void zen::moveFile(const Zstring& sourceFile, const Zstring& targetFile, bool ig { //call back once per file (moveFile() is called by moveDirectory()) if (callback) - switch (callback->requestUiRefresh(sourceFile)) - { - case CallbackMoveFile::CONTINUE: - break; - case CallbackMoveFile::CANCEL: //a user aborted operation IS an error condition! - throw FileError(wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\"") + - wxT("\n\n") + _("Operation aborted!")); - } + callback->requestUiRefresh(sourceFile); const bool targetExisting = fileExists(targetFile); if (targetExisting && !ignoreExisting) //test file existence: e.g. Linux might silently overwrite existing symlinks - throw FileError(wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\"") + - wxT("\n\n") + _("Target file already existing!")); + throw FileError(_("Error moving file:") + "\n\"" + sourceFile + "\" ->\n\"" + targetFile + "\"" + + "\n\n" + _("Target file already existing!")); if (!targetExisting) { @@ -571,10 +588,7 @@ public: return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //DON'T traverse into subdirs; moveDirectory works recursively! } - virtual void onError(const wxString& errorText) - { - throw FileError(errorText); - } + virtual HandleError onError(const std::wstring& errorText) { throw FileError(errorText); } private: NameList& files_; @@ -582,30 +596,20 @@ private: }; -struct RemoveCallbackImpl : public zen::CallbackRemoveDir +struct RemoveCallbackImpl : public CallbackRemoveDir { RemoveCallbackImpl(const Zstring& sourceDir, - const Zstring& targetDir, CallbackMoveFile& moveCallback) : sourceDir_(sourceDir), - targetDir_(targetDir), moveCallback_(moveCallback) {} virtual void notifyDeletion(const Zstring& currentObject) { - switch (moveCallback_.requestUiRefresh(sourceDir_)) - { - case CallbackMoveFile::CONTINUE: - break; - case CallbackMoveFile::CANCEL: //a user aborted operation IS an error condition! - throw zen::FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + zen::zToWx(sourceDir_) + wxT("\" ->\n\"") + - zen::zToWx(targetDir_) + wxT("\"") + wxT("\n\n") + _("Operation aborted!")); - } + moveCallback_.requestUiRefresh(sourceDir_); } private: const Zstring sourceDir_; - const Zstring targetDir_; CallbackMoveFile& moveCallback_; }; } @@ -617,20 +621,13 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool //call back once per folder if (callback) - switch (callback->requestUiRefresh(sourceDir)) - { - case CallbackMoveFile::CONTINUE: - break; - case CallbackMoveFile::CANCEL: //a user aborted operation IS an error condition! - throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") + - zToWx(targetDir) + wxT("\"") + wxT("\n\n") + _("Operation aborted!")); - } + callback->requestUiRefresh(sourceDir); const bool targetExisting = dirExists(targetDir); if (targetExisting && !ignoreExisting) //directory or symlink exists (or even a file... this error will be caught later) - throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") + zToWx(targetDir) + wxT("\"") + - wxT("\n\n") + _("Target directory already existing!")); + throw FileError(_("Error moving directory:") + "\n\"" + sourceDir + "\" ->\n\"" + targetDir + "\"" + + "\n\n" + _("Target directory already existing!")); const bool isSymlink = symlinkExists(sourceDir); @@ -662,9 +659,9 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool TraverseOneLevel traverseCallback(fileList, dirList); traverseFolder(sourceDir, false, traverseCallback); //traverse one level, don't follow symlinks - const Zstring targetDirFormatted = targetDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //ends with path separator + const Zstring targetDirFormatted = targetDir.EndsWith(FILE_NAME_SEPARATOR) ? //ends with path separator targetDir : - targetDir + common::FILE_NAME_SEPARATOR; + targetDir + FILE_NAME_SEPARATOR; //move files for (TraverseOneLevel::NameList::const_iterator i = fileList.begin(); i != fileList.end(); ++i) @@ -678,7 +675,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool } //delete source - std::auto_ptr<RemoveCallbackImpl> removeCallback(callback != NULL ? new RemoveCallbackImpl(sourceDir, targetDir, *callback) : NULL); + std::auto_ptr<RemoveCallbackImpl> removeCallback(callback != NULL ? new RemoveCallbackImpl(sourceDir, *callback) : NULL); removeDirectory(sourceDir, removeCallback.get()); //throw (FileError); } @@ -691,12 +688,12 @@ void zen::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool #elif defined FFS_LINUX const Zstring sourceDirFormatted = //remove trailing slash - sourceDir.size() > 1 && sourceDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' - sourceDir.BeforeLast(common::FILE_NAME_SEPARATOR) : + sourceDir.size() > 1 && sourceDir.EndsWith(FILE_NAME_SEPARATOR) ? //exception: allow '/' + sourceDir.BeforeLast(FILE_NAME_SEPARATOR) : sourceDir; const Zstring targetDirFormatted = //remove trailing slash - targetDir.size() > 1 && targetDir.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' - targetDir.BeforeLast(common::FILE_NAME_SEPARATOR) : + targetDir.size() > 1 && targetDir.EndsWith(FILE_NAME_SEPARATOR) ? //exception: allow '/' + targetDir.BeforeLast(FILE_NAME_SEPARATOR) : targetDir; #endif @@ -727,10 +724,7 @@ public: m_dirs.push_back(fullName); return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //DON'T traverse into subdirs; removeDirectory works recursively! } - virtual void onError(const wxString& errorText) - { - throw FileError(errorText); - } + virtual HandleError onError(const std::wstring& errorText) { throw FileError(errorText); } private: std::vector<Zstring>& m_files; @@ -759,10 +753,8 @@ void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback) #elif defined FFS_LINUX if (::unlink(directory.c_str()) != 0) #endif - { - wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted()); + if (callback) callback->notifyDeletion(directory); //once per symlink return; } @@ -792,8 +784,7 @@ void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback) if (::rmdir(directory.c_str()) != 0) #endif { - wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); + throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted()); } if (callback) callback->notifyDeletion(directory); //and once per folder } @@ -810,10 +801,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool if (!::GetFileAttributesEx(applyLongPathPrefix(sourceObj).c_str(), //__in LPCTSTR lpFileName, GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId, &sourceAttr)) //__out LPVOID lpFileInformation - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); const bool isReparsePoint = (sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; const bool isDirectory = (sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -828,10 +816,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool FILE_FLAG_BACKUP_SEMANTICS, //needed to open a directory; no FILE_FLAG_OPEN_REPARSE_POINT => deref symlinks NULL); if (hSource == INVALID_HANDLE_VALUE) - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hSource); (void)dummy; //silence warning "unused variable" @@ -840,10 +825,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool &creationTime, //__out_opt LPFILETIME lpCreationTime, NULL, //__out_opt LPFILETIME lpLastAccessTime, &lastWriteTime)) //__out_opt LPFILETIME lpLastWriteTime - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); } else { @@ -881,21 +863,29 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool //opening newly created target file may fail due to some AV-software scanning it: no error, we will wait! //http://support.microsoft.com/?scid=kb%3Ben-us%3B316609&x=17&y=20 //-> enable as soon it turns out it is required! - HANDLE hTarget = INVALID_HANDLE_VALUE; /*const int retryInterval = 50; const int maxRetries = 2000 / retryInterval; for (int i = 0; i < maxRetries; ++i) { */ - hTarget = ::CreateFile(applyLongPathPrefix(targetObj).c_str(), - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory - (deRefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //process symlinks - NULL); + + //may need to remove the readonly-attribute (e.g. FAT usb drives) + FileUpdateHandle targetHandle(targetObj, [=]() + { + return ::CreateFile(applyLongPathPrefix(targetObj).c_str(), + FILE_GENERIC_WRITE, //ATTENTION: although FILE_WRITE_ATTRIBUTES should(!) be sufficient, this may leads to access denied on NAS shares, unless we specify FILE_GENERIC_WRITE + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | //needed to open a directory + (deRefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //process symlinks + NULL); + }); + + if (targetHandle.get() == INVALID_HANDLE_VALUE) + throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); + /* if (hTarget == INVALID_HANDLE_VALUE && ::GetLastError() == ERROR_SHARING_VIOLATION) ::Sleep(retryInterval); //wait then retry @@ -904,22 +894,11 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool } */ - if (hTarget == INVALID_HANDLE_VALUE) - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } - Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hTarget); - (void)dummy; //silence warning "unused variable" - - if (!::SetFileTime(hTarget, + if (!::SetFileTime(targetHandle.get(), &creationTime, NULL, &lastWriteTime)) - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); #ifndef NDEBUG //dst hack: verify data written if (dst::isFatDrive(targetObj) && !zen::dirExists(targetObj)) //throw() @@ -939,10 +918,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool { struct stat objInfo = {}; if (::stat(sourceObj.c_str(), &objInfo) != 0) //read file attributes from source directory - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); struct utimbuf newTimes = {}; newTimes.actime = objInfo.st_atime; @@ -950,19 +926,13 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool //(try to) set new "last write time" if (::utime(targetObj.c_str(), &newTimes) != 0) //return value not evaluated! - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); } else { struct stat objInfo = {}; if (::lstat(sourceObj.c_str(), &objInfo) != 0) //read file attributes from source directory - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); struct timeval newTimes[2] = {}; newTimes[0].tv_sec = objInfo.st_atime; /* seconds */ @@ -972,10 +942,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool newTimes[1].tv_usec = 0; /* microseconds */ if (::lutimes(targetObj.c_str(), newTimes) != 0) //return value not evaluated! - { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetObj) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted()); } #endif } @@ -983,28 +950,6 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool namespace { -struct TryCleanUp -{ - static void tryDeleteDir(const Zstring& dirname) //throw () - { - try - { - zen::removeDirectory(dirname, NULL); - } - catch (...) {} - } - - static void tryDeleteFile(const Zstring& filename) //throw () - { - try - { - zen::removeFile(filename); - } - catch (...) {} - } -}; - - #ifdef FFS_WIN Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target path of symbolic link to a directory; throw (FileError) { @@ -1017,10 +962,7 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa FILE_FLAG_BACKUP_SEMANTICS, //needed to open a directory NULL); if (hDir == INVALID_HANDLE_VALUE) - { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zen::zToWx(dirLinkName) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error resolving symbolic link:") + "\n\"" + dirLinkName + "\"" + "\n\n" + zen::getLastErrorFormatted()); Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hDir); (void)dummy; //silence warning "unused variable" @@ -1038,7 +980,7 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa util::getDllFun<GetFinalPathNameByHandleWFunc>(L"kernel32.dll", "GetFinalPathNameByHandleW"); if (getFinalPathNameByHandle == NULL) - throw FileError(wxString(_("Error loading library function:")) + wxT("\n\"") + wxT("GetFinalPathNameByHandleW") + wxT("\"")); + throw FileError(_("Error loading library function:") + "\n\"" + "GetFinalPathNameByHandleW" + "\""); const DWORD rv = getFinalPathNameByHandle( hDir, //__in HANDLE hFile, @@ -1047,8 +989,9 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa 0); //__in DWORD dwFlags if (rv >= BUFFER_SIZE || rv == 0) { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zen::zToWx(dirLinkName) + wxT("\""); - if (rv == 0) errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(); + std::wstring errorMessage = _("Error resolving symbolic link:") + "\n\"" + dirLinkName + "\""; + if (rv == 0) + errorMessage += L"\n\n" + zen::getLastErrorFormatted(); throw FileError(errorMessage); } @@ -1061,8 +1004,6 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa //copy SELinux security context void copySecurityContext(const Zstring& source, const Zstring& target, bool derefSymlinks) //throw (FileError) { - using zen::zToWx; - security_context_t contextSource = NULL; const int rv = derefSymlinks ? ::getfilecon (source.c_str(), &contextSource) : @@ -1073,8 +1014,7 @@ void copySecurityContext(const Zstring& source, const Zstring& target, bool dere errno == EOPNOTSUPP) //extended attributes are not supported by the filesystem return; - wxString errorMessage = wxString(_("Error reading security context:")) + wxT("\n\"") + zToWx(source) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); + throw FileError(_("Error reading security context:") + "\n\"" + source + "\"" + "\n\n" + zen::getLastErrorFormatted()); } Loki::ScopeGuard dummy1 = Loki::MakeGuard(::freecon, contextSource); (void)dummy1; //silence warning "unused variable" @@ -1104,10 +1044,7 @@ void copySecurityContext(const Zstring& source, const Zstring& target, bool dere ::setfilecon (target.c_str(), contextSource) : ::lsetfilecon(target.c_str(), contextSource); if (rv3 < 0) - { - wxString errorMessage = wxString(_("Error writing security context:")) + wxT("\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error writing security context:") + "\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted()); } #endif //HAVE_SELINUX @@ -1130,8 +1067,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de } catch (const FileError& e) { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + e.msg()); + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + e.msg()); } PSECURITY_DESCRIPTOR buffer = NULL; @@ -1149,64 +1085,46 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de FILE_FLAG_BACKUP_SEMANTICS | (derefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), //FILE_FLAG_BACKUP_SEMANTICS needed to open a directory NULL); if (hSource == INVALID_HANDLE_VALUE) - { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (OR)")); - } + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (OR)"); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hSource); (void)dummy; //silence warning "unused variable" // DWORD rc = ::GetNamedSecurityInfo(const_cast<WCHAR*>(applyLongPathPrefix(source).c_str()), -> does NOT dereference symlinks! - DWORD rc = ::GetSecurityInfo( - hSource, //__in LPTSTR pObjectName, - SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, - OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInfo, - &owner, //__out_opt PSID *ppsidOwner, - &group, //__out_opt PSID *ppsidGroup, - &dacl, //__out_opt PACL *ppDacl, - &sacl, //__out_opt PACL *ppSacl, - &buffer); //__out_opt PSECURITY_DESCRIPTOR *ppSecurityDescriptor + DWORD rc = ::GetSecurityInfo(hSource, //__in LPTSTR pObjectName, + SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInfo, + &owner, //__out_opt PSID *ppsidOwner, + &group, //__out_opt PSID *ppsidGroup, + &dacl, //__out_opt PACL *ppDacl, + &sacl, //__out_opt PACL *ppSacl, + &buffer); //__out_opt PSECURITY_DESCRIPTOR *ppSecurityDescriptor if (rc != ERROR_SUCCESS) - { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted(rc) + wxT(" (R)")); - } + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted(rc) + " (R)"); Loki::ScopeGuard dummy4 = Loki::MakeGuard(::LocalFree, buffer); (void)dummy4; //silence warning "unused variable" - const Zstring targetFmt = zen::applyLongPathPrefix(target); - - //read-only file attribute may cause trouble: temporarily reset it - const DWORD targetAttr = ::GetFileAttributes(targetFmt.c_str()); - Loki::ScopeGuard resetAttributes = Loki::MakeGuard(::SetFileAttributes, targetFmt.c_str(), targetAttr); - if (targetAttr != INVALID_FILE_ATTRIBUTES && - (targetAttr & FILE_ATTRIBUTE_READONLY)) - ::SetFileAttributes(targetFmt.c_str(), targetAttr & (~FILE_ATTRIBUTE_READONLY)); //try to... - else - resetAttributes.Dismiss(); - - - const HANDLE hTarget = ::CreateFile( targetFmt.c_str(), // lpFileName - FILE_GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY, // dwDesiredAccess: all four seem to be required!!! - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // dwShareMode - NULL, // lpSecurityAttributes - OPEN_EXISTING, // dwCreationDisposition - FILE_FLAG_BACKUP_SEMANTICS | (derefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), // dwFlagsAndAttributes - NULL); // hTemplateFile - if (hTarget == INVALID_HANDLE_VALUE) + //may need to remove the readonly-attribute (e.g. FAT usb drives) + FileUpdateHandle targetHandle(target, [=]() { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (OW)")); - } - Loki::ScopeGuard dummy2 = Loki::MakeGuard(::CloseHandle, hTarget); - (void)dummy2; //silence warning "unused variable" + return ::CreateFile(applyLongPathPrefix(target).c_str(), // lpFileName + FILE_GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY, // dwDesiredAccess: all four seem to be required!!! + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // dwShareMode + NULL, // lpSecurityAttributes + OPEN_EXISTING, // dwCreationDisposition + FILE_FLAG_BACKUP_SEMANTICS | (derefSymlinks ? 0 : FILE_FLAG_OPEN_REPARSE_POINT), // dwFlagsAndAttributes + NULL); // hTemplateFile + }); + + if (targetHandle.get() == INVALID_HANDLE_VALUE) + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (OW)"); // rc = ::SetNamedSecurityInfo(const_cast<WCHAR*>(applyLongPathPrefix(target).c_str()), //__in LPTSTR pObjectName, -> does NOT dereference symlinks! rc = ::SetSecurityInfo( - hTarget, //__in LPTSTR pObjectName, - SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, + targetHandle.get(), //__in LPTSTR pObjectName, + SE_FILE_OBJECT, //__in SE_OBJECT_TYPE ObjectType, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInfo, owner, //__in_opt PSID psidOwner, group, //__in_opt PSID psidGroup, @@ -1214,10 +1132,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de sacl); //__in_opt PACL pSacl if (rc != ERROR_SUCCESS) - { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted(rc) + wxT(" (W)")); - } + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted(rc) + " (W)"); #elif defined FFS_LINUX @@ -1227,30 +1142,32 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de if (derefSymlinks) { - struct stat fileInfo; + struct stat fileInfo = {}; if (::stat (source.c_str(), &fileInfo) != 0 || ::chown(target.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0 || // may require admin rights! ::chmod(target.c_str(), fileInfo.st_mode) != 0) - { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (R)")); - } + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (R)"); } else { - struct stat fileInfo; + struct stat fileInfo = {}; if (::lstat (source.c_str(), &fileInfo) != 0 || ::lchown(target.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0 || // may require admin rights! (!symlinkExists(target) && ::chmod(target.c_str(), fileInfo.st_mode) != 0)) //setting access permissions doesn't make sense for symlinks on Linux: there is no lchmod() - { - const wxString errorMessage = wxString(_("Error copying file permissions:")) + wxT("\n\"") + zToWx(source) + wxT("\" ->\n\"") + zToWx(target) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (W)")); - } + throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (W)"); } #endif } +namespace +{ +//provide uniform binary interface: +void removeDirSimple(const Zstring& directory) { zen::removeDirectory(directory); } //throw (FileError) +void removeFileSimple(const Zstring& filename) { zen::removeFile(filename); } //throw (FileError) +} + + void createDirectoryRecursively(const Zstring& directory, const Zstring& templateDir, bool copyFilePermissions, int level) { using namespace zen; @@ -1262,11 +1179,11 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat return; //try to create parent folders first - const Zstring dirParent = directory.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring dirParent = directory.BeforeLast(FILE_NAME_SEPARATOR); if (!dirParent.empty() && !zen::dirExists(dirParent)) { //call function recursively - const Zstring templateParent = templateDir.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring templateParent = templateDir.BeforeLast(FILE_NAME_SEPARATOR); createDirectoryRecursively(dirParent, templateParent, copyFilePermissions, level + 1); } @@ -1284,8 +1201,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat #endif { if (level != 0) return; - wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); + throw FileError(_("Error creating directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted()); } if (!templateDir.empty()) @@ -1351,14 +1267,14 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat } #endif - //try to copy file times: NOT mission critical for a directory + //try to copy file times: NOT mission critical for a directory, since modification time is changed on each added, deleted file, however creation time will stay try { copyFileTimes(templateDir, directory, true); //throw (FileError) } catch (FileError&) {} - Loki::ScopeGuard guardNewDir = Loki::MakeGuard(&TryCleanUp::tryDeleteDir, directory); //ensure cleanup: + Loki::ScopeGuard guardNewDir = Loki::MakeGuard(&removeDirSimple, directory); //ensure cleanup: //enforce copying file permissions: it's advertized on GUI... if (copyFilePermissions) @@ -1373,12 +1289,12 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat void zen::createDirectory(const Zstring& directory, const Zstring& templateDir, bool copyFilePermissions) { //remove trailing separator - const Zstring dirFormatted = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? - directory.BeforeLast(common::FILE_NAME_SEPARATOR) : + const Zstring dirFormatted = directory.EndsWith(FILE_NAME_SEPARATOR) ? + directory.BeforeLast(FILE_NAME_SEPARATOR) : directory; - const Zstring templateFormatted = templateDir.EndsWith(common::FILE_NAME_SEPARATOR) ? - templateDir.BeforeLast(common::FILE_NAME_SEPARATOR) : + const Zstring templateFormatted = templateDir.EndsWith(FILE_NAME_SEPARATOR) ? + templateDir.BeforeLast(FILE_NAME_SEPARATOR) : templateDir; createDirectoryRecursively(dirFormatted, templateFormatted, copyFilePermissions, 0); @@ -1400,29 +1316,23 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, zen: typedef BOOLEAN (WINAPI *CreateSymbolicLinkFunc)(LPCTSTR lpSymlinkFileName, LPCTSTR lpTargetFileName, DWORD dwFlags); static const CreateSymbolicLinkFunc createSymbolicLink = util::getDllFun<CreateSymbolicLinkFunc>(L"kernel32.dll", "CreateSymbolicLinkW"); if (createSymbolicLink == NULL) - throw FileError(wxString(_("Error loading library function:")) + wxT("\n\"") + wxT("CreateSymbolicLinkW") + wxT("\"")); + throw FileError(_("Error loading library function:") + "\n\"" + "CreateSymbolicLinkW" + "\""); if (!createSymbolicLink( //seems no long path prefix is required... targetLink.c_str(), //__in LPTSTR lpSymlinkFileName, linkPath.c_str(), //__in LPTSTR lpTargetFileName, (type == SYMLINK_TYPE_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0))) //__in DWORD dwFlags - { - const wxString errorMessage = wxString(_("Error copying symbolic link:")) + wxT("\n\"") + zToWx(sourceLink) + wxT("\" ->\n\"") + zToWx(targetLink) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + zen::getLastErrorFormatted()); #elif defined FFS_LINUX if (::symlink(linkPath.c_str(), targetLink.c_str()) != 0) - { - const wxString errorMessage = wxString(_("Error copying symbolic link:")) + wxT("\n\"") + zToWx(sourceLink) + wxT("\" ->\n\"") + zToWx(targetLink) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + zen::getLastErrorFormatted()); #endif //allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist Loki::ScopeGuard guardNewDir = type == SYMLINK_TYPE_DIR ? - Loki::MakeGuard(&TryCleanUp::tryDeleteDir, targetLink) : - Loki::MakeGuard(&TryCleanUp::tryDeleteFile, targetLink); + Loki::MakeGuard(&removeDirSimple, targetLink) : + Loki::MakeGuard(&removeFileSimple, targetLink); //file times: essential for a symlink: enforce this! (don't just try!) copyFileTimes(sourceLink, targetLink, false); //throw (FileError) @@ -1448,6 +1358,18 @@ Zstring createTempName(const Zstring& filename) } #ifdef FFS_WIN +struct CallbackData +{ + CallbackData(CallbackCopyFile& cb) : + callback(cb), + exceptionCaught(false) {} + + CallbackCopyFile& callback; + bool exceptionCaught; + zen::UInt64 bytesTransferredOnException; +}; + + DWORD CALLBACK copyCallbackInternal( LARGE_INTEGER totalFileSize, LARGE_INTEGER totalBytesTransferred, @@ -1459,36 +1381,30 @@ DWORD CALLBACK copyCallbackInternal( HANDLE hDestinationFile, LPVOID lpData) { - using zen::CallbackCopyFile; - //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size). static size_t callNr = 0; if (++callNr % 4 == 0) //executing callback every 256 kB should suffice { - if (lpData != NULL) + if (lpData) { + CallbackData& cbd = *static_cast<CallbackData*>(lpData); + //some odd check for some possible(?) error condition if (totalBytesTransferred.QuadPart < 0) //let's see if someone answers the call... - ::MessageBox(NULL, wxT("You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\ + ::MessageBox(NULL, L"You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\ Please write a mail to the author of FreeFileSync at zhnmju123@gmx.de and simply state that\n\ \"totalBytesTransferred.HighPart can be below zero\"!\n\n\ - This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu"), + This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu", NULL, 0); - - CallbackCopyFile* callback = static_cast<CallbackCopyFile*>(lpData); try { - switch (callback->updateCopyStatus(zen::UInt64(totalBytesTransferred.QuadPart))) - { - case CallbackCopyFile::CONTINUE: - break; - case CallbackCopyFile::CANCEL: - return PROGRESS_CANCEL; - } + cbd.callback.updateCopyStatus(zen::UInt64(totalBytesTransferred.QuadPart)); } catch (...) { - ::MessageBox(NULL, wxT("Exception in callback zen::copyFile! Please contact the author of FFS."), NULL, 0); + cbd.exceptionCaught = true; + cbd.bytesTransferredOnException = zen::UInt64(totalBytesTransferred.QuadPart); + return PROGRESS_CANCEL; } } } @@ -1549,21 +1465,26 @@ void rawCopyWinApi(const Zstring& sourceFile, if (nonEncSupported) copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION; + std::unique_ptr<CallbackData> cbd(callback ? new CallbackData(*callback) : NULL); + if (!::CopyFileEx( //same performance like CopyFile() applyLongPathPrefix(sourceFile).c_str(), applyLongPathPrefix(targetFile).c_str(), - callback != NULL ? copyCallbackInternal : NULL, - callback, + callback ? copyCallbackInternal : NULL, + cbd.get(), NULL, copyFlags)) { + if (cbd.get() && cbd->exceptionCaught) + callback->updateCopyStatus(cbd->bytesTransferredOnException); //rethrow (hopefully!) + const DWORD lastError = ::GetLastError(); //don't suppress "lastError == ERROR_REQUEST_ABORTED": a user aborted operation IS an error condition! //assemble error message... - wxString errorMessage = wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"") + - wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error copying file:") + "\n\"" + sourceFile + "\" ->\n\"" + targetFile + "\"" + + "\n\n" + zen::getLastErrorFormatted(lastError); //if file is locked (try to) use Windows Volume Shadow Copy Service if (lastError == ERROR_SHARING_VIOLATION || @@ -1588,15 +1509,27 @@ void rawCopyWinApi(const Zstring& sourceFile, if (lastError == ERROR_INVALID_PARAMETER && dst::isFatDrive(targetFile) && getFilesize(sourceFile) >= 4U * zen::UInt64(1024U * 1024 * 1024)) //throw (FileError) - errorMessage += wxT("\nFAT volume cannot store files larger than 4 gigabyte!"); + errorMessage += L"\nFAT volume cannot store files larger than 4 gigabyte!"; } catch(...) {} throw FileError(errorMessage); } - //adapt file modification time: - copyFileTimes(sourceFile, targetFile, true); //throw (FileError) + try //adapt file modification time + { + //this is optional, since ::CopyFileEx already copies modification time (but not creation time) + //chances are good this also avoids a number of unnecessary access-denied errors on NAS shares! + //(one is: missing permission to change file attributes, remove read-only in particular) + copyFileTimes(sourceFile, targetFile, true); //throw FileError + } + catch (FileError&) + { + //CAVEAT: in case one of the drives is FAT, we still(!) need copyFileTimes to apply the DST hack! + if (dst::isFatDrive(sourceFile) || dst::isFatDrive(targetFile)) //throw() + throw; + assert(false); //maybe this catches some test-case left-overs? + } guardTarget.Dismiss(); //target has been created successfully! } @@ -1632,7 +1565,7 @@ void rawCopyWinApi(const Zstring& sourceFile, // if (hFileIn == INVALID_HANDLE_VALUE) // { // const DWORD lastError = ::GetLastError(); -// const wxString& errorMessage = wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + wxT("\n\n") + zen::getLastErrorFormatted(lastError); +// const std::wstring& errorMessage = _("Error opening file:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); // // //if file is locked (try to) use Windows Volume Shadow Copy Service // if (lastError == ERROR_SHARING_VIOLATION || @@ -1647,10 +1580,7 @@ void rawCopyWinApi(const Zstring& sourceFile, // // BY_HANDLE_FILE_INFORMATION infoFileIn = {}; // if (!::GetFileInformationByHandle(hFileIn, &infoFileIn)) -// { -// const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); -// throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); -// } +// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted()); // // //####################################### DST hack ########################################### // if (dst::isFatDrive(sourceFile)) //throw() @@ -1689,8 +1619,8 @@ void rawCopyWinApi(const Zstring& sourceFile, // if (hFileOut == INVALID_HANDLE_VALUE) // { // const DWORD lastError = ::GetLastError(); -// const wxString& errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted(lastError); +// const std::wstring& errorMessage = _("Error writing file:") + "\n\"" + targetFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted(lastError); // // if (lastError == ERROR_FILE_EXISTS) // throw ErrorTargetExisting(errorMessage); @@ -1718,10 +1648,7 @@ void rawCopyWinApi(const Zstring& sourceFile, // &fsFlags, //__out_opt LPDWORD lpFileSystemFlags, // NULL, //__out LPTSTR lpFileSystemNameBuffer, // 0)) //__in DWORD nFileSystemNameSize -// { -// const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); -// throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); -// } +// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted()); // // const bool sourceIsEncrypted = (infoFileIn.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0; // const bool sourceIsCompressed = (infoFileIn.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0; @@ -1747,9 +1674,9 @@ void rawCopyWinApi(const Zstring& sourceFile, // 0, //OutBufferSize // &bytesReturned, //number of bytes returned // NULL)) //OVERLAPPED structure -// throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted() + -// wxT("\nFailed to write NTFS compressed attribute!")); +// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted() + +// "\nFailed to write NTFS compressed attribute!"); // } // // //although it seems the sparse attribute is set automatically by BackupWrite, we are required to do this manually: http://support.microsoft.com/kb/271398/en-us @@ -1766,9 +1693,9 @@ void rawCopyWinApi(const Zstring& sourceFile, // 0, //OutBufferSize // &bytesReturned, //number of bytes returned // NULL)) //OVERLAPPED structure -// throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted() + -// wxT("\nFailed to write NTFS sparse attribute!")); +// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted() + +// "\nFailed to write NTFS sparse attribute!"); // } // } // @@ -1808,20 +1735,20 @@ void rawCopyWinApi(const Zstring& sourceFile, // false, //__in BOOL bAbort, // false, //__in BOOL bProcessSecurity, // &context.read)) //__out LPVOID *lpContext -// throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted()); +// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted()); // } // else if (!::ReadFile(hFileIn, //__in HANDLE hFile, // memory.get(), //__out LPVOID lpBuffer, // BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead, // &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead, // NULL)) //__inout_opt LPOVERLAPPED lpOverlapped -// throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted()); +// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted()); // // if (bytesRead > BUFFER_SIZE) -// throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + -// wxT("\n\n") + wxT("buffer overflow")); +// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" + +// "\n\n" + "buffer overflow"); // // if (bytesRead < BUFFER_SIZE) // eof = true; @@ -1837,20 +1764,19 @@ void rawCopyWinApi(const Zstring& sourceFile, // false, //__in BOOL bAbort, // false, //__in BOOL bProcessSecurity, // &context.write)) //__out LPVOID *lpContext -// throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! +// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message! // } // else if (!::WriteFile(hFileOut, //__in HANDLE hFile, // memory.get(), //__out LPVOID lpBuffer, // bytesRead, //__in DWORD nNumberOfBytesToWrite, // &bytesWritten, //__out_opt LPDWORD lpNumberOfBytesWritten, // NULL)) //__inout_opt LPOVERLAPPED lpOverlapped -// throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! +// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + +// "\n\n" + zen::getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message! // // if (bytesWritten != bytesRead) -// throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + wxT("incomplete write")); +// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + "\n\n" + "incomplete write"); // // totalBytesTransferred += bytesRead; // @@ -1866,8 +1792,8 @@ void rawCopyWinApi(const Zstring& sourceFile, // break; // // case CallbackCopyFile::CANCEL: //a user aborted operation IS an error condition! -// throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + -// zToWx(targetFile) + wxT("\"\n\n") + _("Operation aborted!")); +// throw FileError(_("Error copying file:") + "\n\"" + sourceFile + "\" ->\n\"" + +// targetFile + "\"\n\n" + _("Operation aborted!")); // } // } // while (!eof); @@ -1877,12 +1803,10 @@ void rawCopyWinApi(const Zstring& sourceFile, // { // LARGE_INTEGER inputSize = {}; // if (!::GetFileSizeEx(hFileIn, &inputSize)) -// throw FileError(wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted()); +// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted()); // // if (inputSize.QuadPart != 0) -// throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"") + -// wxT("\n\n") + wxT("unknown error")); +// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" + "\n\n" + "unknown error"); // } // // //time needs to be set at the end: BackupWrite() changes file time @@ -1890,8 +1814,7 @@ void rawCopyWinApi(const Zstring& sourceFile, // &infoFileIn.ftCreationTime, // NULL, // &infoFileIn.ftLastWriteTime)) -// throw FileError(wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"") + -// wxT("\n\n") + zen::getLastErrorFormatted()); +// throw FileError(_("Error changing modification time:") + "\n\"" + targetFile + "\"" + "\n\n" + zen::getLastErrorFormatted()); // // //#ifndef NDEBUG //dst hack: verify data written @@ -1969,15 +1892,7 @@ void rawCopyStream(const Zstring& sourceFile, //invoke callback method to update progress indicators if (callback != NULL) - switch (callback->updateCopyStatus(totalBytesTransferred)) - { - case CallbackCopyFile::CONTINUE: - break; - - case CallbackCopyFile::CANCEL: //a user aborted operation IS an error condition! - throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + - zToWx(targetFile) + wxT("\"\n\n") + _("Operation aborted!")); - } + callback->updateCopyStatus(totalBytesTransferred); } while (!fileIn.eof()); } @@ -2034,7 +1949,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw (FileError: ErrorTargetPat //raw file copy try { - copyFileImpl(sourceFile, temporary, callback); //throw (FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked) + copyFileImpl(sourceFile, temporary, callback); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked } catch (ErrorTargetExisting&) { @@ -2043,7 +1958,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw (FileError: ErrorTargetPat temporary = createTempName(targetFile); //retry - copyFileImpl(sourceFile, temporary, callback); //throw (FileError) + copyFileImpl(sourceFile, temporary, callback); //throw FileError } //have target file deleted (after read access on source and target has been confirmed) => allow for almost transactional overwrite diff --git a/shared/file_handling.h b/shared/file_handling.h index 67540de5..0ee4b1e9 100644 --- a/shared/file_handling.h +++ b/shared/file_handling.h @@ -37,7 +37,7 @@ ResponseSameVol onSameVolume(const Zstring& folderLeft, const Zstring& folderRig void copyFileTimes(const Zstring& sourceDir, const Zstring& targetDir, bool derefSymlinks); //throw (FileError) //symlink handling: always evaluate target -zen::UInt64 getFilesize(const Zstring& filename); //throw (FileError) +UInt64 getFilesize(const Zstring& filename); //throw (FileError) //file handling @@ -88,19 +88,6 @@ struct CallbackRemoveDir }; -struct CallbackMoveFile //callback functionality -{ - virtual ~CallbackMoveFile() {} - - enum Response - { - CONTINUE, - CANCEL - }; - virtual Response requestUiRefresh(const Zstring& currentObject) = 0; //DON'T throw exceptions here, at least in Windows build! -}; - - struct CallbackCopyFile //callback functionality { virtual ~CallbackCopyFile() {} @@ -109,12 +96,17 @@ struct CallbackCopyFile //callback functionality //at this point full read access on source had been proven, so it's safe to delete it. virtual void deleteTargetFile(const Zstring& targetFile) = 0; //may throw exceptions - enum Response - { - CONTINUE, - CANCEL - }; - virtual Response updateCopyStatus(zen::UInt64 totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build! + //may throw: + //Linux: unconditionally + //Windows: first exception is swallowed, requestUiRefresh() is then called again where it may throw again and exception will propagate as expected + virtual void updateCopyStatus(UInt64 totalBytesTransferred) = 0; +}; + + +struct CallbackMoveFile //callback functionality +{ + virtual ~CallbackMoveFile() {} + virtual void requestUiRefresh(const Zstring& currentObject) = 0; //see CallbackCopyFile! }; } diff --git a/shared/file_id.cpp b/shared/file_id.cpp index b111b9a2..da8fd815 100644 --- a/shared/file_id.cpp +++ b/shared/file_id.cpp @@ -36,7 +36,6 @@ std::string util::retrieveFileID(const Zstring& filename) //WARNING: CreateFile() is SLOW, while GetFileInformationByHandle() is cheap! //http://msdn.microsoft.com/en-us/library/aa363788(VS.85).aspx - //privilege SE_BACKUP_NAME doesn't seem to be required here at all const HANDLE hFile = ::CreateFile(zen::applyLongPathPrefix(filename).c_str(), @@ -68,13 +67,16 @@ std::string util::retrieveFileID(const Zstring& filename) fileID += numberToBytes(fileInfo.st_ino); } #endif - + assert(!fileID.empty()); return fileID; } bool util::sameFileSpecified(const Zstring& file1, const Zstring& file2) { + if (EqualFilename()(file1, file2)) //quick check + return true; + const std::string id1 = retrieveFileID(file1); const std::string id2 = retrieveFileID(file2); diff --git a/shared/file_io.cpp b/shared/file_io.cpp index 51f81da9..c19101aa 100644 --- a/shared/file_io.cpp +++ b/shared/file_io.cpp @@ -5,7 +5,6 @@ // ************************************************************************** // #include "file_io.h" -#include "string_conv.h" #include "last_error.h" #include "i18n.h" @@ -31,7 +30,7 @@ FileInput::FileInput(const Zstring& filename) : //throw (FileError, ErrorNotExi #ifdef FFS_WIN fileHandle = ::CreateFile(zen::applyLongPathPrefix(filename).c_str(), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //all shared modes are required to read files that are open in other applications + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //all shared modes are required to read open files that are shared by other applications NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, @@ -64,8 +63,7 @@ FileInput::FileInput(const Zstring& filename) : //throw (FileError, ErrorNotExi { const DWORD lastError = ::GetLastError(); - wxString errorMessage = wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error opening file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_PATH_NOT_FOUND) @@ -73,14 +71,14 @@ FileInput::FileInput(const Zstring& filename) : //throw (FileError, ErrorNotExi throw FileError(errorMessage); } + #elif defined FFS_LINUX fileHandle = ::fopen(filename.c_str(), "r,type=record,noseek"); //utilize UTF-8 filename if (fileHandle == NULL) { const int lastError = errno; - wxString errorMessage = wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error opening file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == ENOENT) throw ErrorNotExisting(errorMessage); @@ -114,10 +112,7 @@ size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number const size_t bytesRead = ::fread(buffer, 1, bytesToRead, fileHandle); if (::ferror(fileHandle) != 0) #endif - { - wxString errorMessage = wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error reading file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted()); #ifdef FFS_WIN if (bytesRead < bytesToRead) //falsify only! @@ -127,10 +122,7 @@ size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number eofReached = true; if (bytesRead > bytesToRead) - { - wxString errorMessage = wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + wxT("buffer overflow")); - } + throw FileError(_("Error reading file:") + "\n\"" + filename_ + "\"" + "\n\n" + "buffer overflow"); return bytesRead; } @@ -151,7 +143,7 @@ FileOutput::FileOutput(const Zstring& filename, AccessFlag access) : //throw (Fi #ifdef FFS_WIN fileHandle = ::CreateFile(zen::applyLongPathPrefix(filename).c_str(), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //note: FILE_SHARE_DELETE is required to rename file while handle is open! + FILE_SHARE_READ | FILE_SHARE_DELETE, //note: FILE_SHARE_DELETE is required to rename file while handle is open! NULL, access == ACC_OVERWRITE ? CREATE_ALWAYS : CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, @@ -159,8 +151,7 @@ FileOutput::FileOutput(const Zstring& filename, AccessFlag access) : //throw (Fi if (fileHandle == INVALID_HANDLE_VALUE) { const DWORD lastError = ::GetLastError(); - wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error writing file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == ERROR_FILE_EXISTS) throw ErrorTargetExisting(errorMessage); @@ -178,8 +169,7 @@ FileOutput::FileOutput(const Zstring& filename, AccessFlag access) : //throw (Fi if (fileHandle == NULL) { const int lastError = errno; - wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - errorMessage += wxT("\n\n") + zen::getLastErrorFormatted(lastError); + std::wstring errorMessage = _("Error writing file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); if (lastError == EEXIST) throw ErrorTargetExisting(errorMessage); @@ -215,14 +205,8 @@ void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw (FileErr const size_t bytesWritten = ::fwrite(buffer, 1, bytesToWrite, fileHandle); if (::ferror(fileHandle) != 0) #endif - { - wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message! - } + throw FileError(_("Error writing file:") + "\n\"" + filename_ + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message! if (bytesWritten != bytesToWrite) //must be fulfilled for synchronous writes! - { - wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + wxT("incomplete write")); - } + throw FileError(_("Error writing file:") + "\n\"" + filename_ + "\"" + "\n\n" + "incomplete write"); } diff --git a/shared/file_io.h b/shared/file_io.h index d311346a..79b521f1 100644 --- a/shared/file_io.h +++ b/shared/file_io.h @@ -37,6 +37,9 @@ public: bool eof(); //end of file reached private: + FileInput(const FileInput&); + FileInput& operator=(const FileInput&); + bool eofReached; FileHandle fileHandle; const Zstring filename_; @@ -58,6 +61,9 @@ public: void write(const void* buffer, size_t bytesToWrite); //throw (FileError) private: + FileOutput(const FileOutput&); + FileOutput& operator=(const FileOutput&); + FileHandle fileHandle; const Zstring filename_; }; diff --git a/shared/file_traverser.cpp b/shared/file_traverser.cpp index 2525be58..aced3487 100644 --- a/shared/file_traverser.cpp +++ b/shared/file_traverser.cpp @@ -6,9 +6,7 @@ // #include "file_traverser.h" #include <limits> -#include "system_constants.h" #include "last_error.h" -#include "string_conv.h" #include "assert_static.h" #include "symlink_target.h" @@ -23,6 +21,36 @@ #include <cerrno> #endif +using namespace zen; + + +namespace +{ +//implement "retry" in a generic way: + +//returns "true" if "cmd" was invoked successfully, "false" if error occured and was ignored +template <class Command> inline //function object with bool operator()(std::wstring& errorMsg), returns "true" on success, "false" on error and writes "errorMsg" in this case +bool tryReportingError(Command cmd, zen::TraverseCallback& callback) +{ + for (;;) + { + std::wstring errorMsg; + if (cmd(errorMsg)) + return true; + + switch (callback.onError(errorMsg)) + { + case TraverseCallback::TRAV_ERROR_RETRY: + break; + case TraverseCallback::TRAV_ERROR_IGNORE: + return false; + default: + assert(false); + break; + } + } +} + #ifdef FFS_WIN inline @@ -62,6 +90,7 @@ bool setWin32FileInformationFromSymlink(const Zstring& linkName, zen::TraverseCa return true; } #endif +} class DirTraverser @@ -78,8 +107,8 @@ public: #elif defined FFS_LINUX const Zstring directoryFormatted = //remove trailing slash - baseDirectory.size() > 1 && baseDirectory.EndsWith(common::FILE_NAME_SEPARATOR) ? //exception: allow '/' - baseDirectory.BeforeLast(common::FILE_NAME_SEPARATOR) : + baseDirectory.size() > 1 && baseDirectory.EndsWith(FILE_NAME_SEPARATOR) ? //exception: allow '/' + baseDirectory.BeforeLast(FILE_NAME_SEPARATOR) : baseDirectory; #endif @@ -97,40 +126,56 @@ public: } private: + DirTraverser(const DirTraverser&); + DirTraverser& operator=(const DirTraverser&); + template <bool followSymlinks> void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level) { - using namespace zen; + using namespace zen; - if (level == 100) //catch endless recursion + tryReportingError([&](std::wstring& errorMsg) -> bool { - sink.onError(wxString(_("Endless loop when traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"")); - return; - } + if (level == 100) //notify endless recursion + { + errorMsg = _("Endless loop when traversing directory:") + "\n\"" + directory + "\""; + return false; + } + return true; + }, sink); + #ifdef FFS_WIN //ensure directoryFormatted ends with backslash - const Zstring& directoryFormatted = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? + const Zstring& directoryFormatted = directory.EndsWith(FILE_NAME_SEPARATOR) ? directory : - directory + common::FILE_NAME_SEPARATOR; + directory + FILE_NAME_SEPARATOR; WIN32_FIND_DATA fileInfo = {}; - HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryFormatted + Zchar('*')).c_str(), //__in LPCTSTR lpFileName - &fileInfo); //__out LPWIN32_FIND_DATA lpFindFileData - //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH - if (searchHandle == INVALID_HANDLE_VALUE) + HANDLE searchHandle = INVALID_HANDLE_VALUE; + tryReportingError([&](std::wstring& errorMsg) -> bool { - const DWORD lastError = ::GetLastError(); - if (lastError == ERROR_FILE_NOT_FOUND) - return; + searchHandle = ::FindFirstFile( + applyLongPathPrefix(directoryFormatted + Zchar('*')).c_str(), //__in LPCTSTR lpFileName + &fileInfo); //__out LPWIN32_FIND_DATA lpFindFileData + //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH - //else: we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); + if (searchHandle == INVALID_HANDLE_VALUE) + { + const DWORD lastError = ::GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND) + return true; //fine: empty directory - sink.onError(errorMessage + wxT("\n\n") +zen::getLastErrorFormatted(lastError)); - return; - } + //else: we have a problem... report it: + errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError); + return false; + } + return true; + }, sink); + + if (searchHandle == INVALID_HANDLE_VALUE) + return; //empty dir or ignore error Loki::ScopeGuard dummy = Loki::MakeGuard(::FindClose, searchHandle); (void)dummy; //silence warning "unused variable" @@ -139,9 +184,8 @@ private: { //don't return "." and ".." const Zchar* const shortName = fileInfo.cFileName; - if ( shortName[0] == Zstr('.') && - ((shortName[1] == Zstr('.') && shortName[2] == Zstr('\0')) || - shortName[1] == Zstr('\0'))) + if (shortName[0] == L'.' && + (shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0'))) continue; const Zstring& fullName = directoryFormatted + shortName; @@ -210,65 +254,95 @@ private: details.fileSize = zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); } - sink.onFile(shortName, fullName, details); + sink.onFile(shortName, fullName, details); } } - while (::FindNextFile(searchHandle, // handle to search - &fileInfo)); // pointer to structure for data on found file + while ([&]() -> bool + { + bool moreData = false; - const DWORD lastError = ::GetLastError(); - if (lastError != ERROR_NO_MORE_FILES) //this is fine + tryReportingError([&](std::wstring& errorMsg) -> bool { - //else we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink.onError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted(lastError)); - } + if (!::FindNextFile(searchHandle, // handle to search + &fileInfo)) // pointer to structure for data on found file + { + if (::GetLastError() == ERROR_NO_MORE_FILES) //this is fine + return true; + + //else we have a problem... report it: + errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(); + return false; + } + + moreData = true; + return true; + }, sink); + + return moreData; + }()); + #elif defined FFS_LINUX - DIR* dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/" - if (dirObj == NULL) - { - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink.onError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - return; - } + DIR* dirObj = NULL; + if (!tryReportingError([&](std::wstring& errorMsg) -> bool + { + dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/" + if (dirObj == NULL) + { + errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(); + return false; + } + return true; + }, sink)) + return; Loki::ScopeGuard dummy = Loki::MakeGuard(::closedir, dirObj); //never close NULL handles! -> crash (void)dummy; //silence warning "unused variable" while (true) { - errno = 0; //set errno to 0 as unfortunately this isn't done when readdir() returns NULL because it can't find any files - struct dirent* dirEntry = ::readdir(dirObj); - if (dirEntry == NULL) + struct dirent* dirEntry = NULL; + tryReportingError([&](std::wstring& errorMsg) -> bool { - if (errno == 0) - return; //everything okay + errno = 0; //set errno to 0 as unfortunately this isn't done when readdir() returns NULL because it can't find any files + dirEntry = ::readdir(dirObj); + if (dirEntry == NULL) + { + if (errno == 0) + return true; //everything okay, not more items - //else: we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; - sink.onError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); + //else: we have a problem... report it: + errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(); + return false; + } + return true; + }, sink); + if (dirEntry == NULL) //no more items or ignore error return; - } + //don't return "." and ".." const Zchar* const shortName = dirEntry->d_name; - if ( shortName[0] == Zstr('.') && - ((shortName[1] == Zstr('.') && shortName[2] == Zstr('\0')) || - shortName[1] == Zstr('\0'))) + if (shortName[0] == '.' && + (shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0'))) continue; - const Zstring& fullName = directory.EndsWith(common::FILE_NAME_SEPARATOR) ? //e.g. "/" + const Zstring& fullName = directory.EndsWith(FILE_NAME_SEPARATOR) ? //e.g. "/" directory + shortName : - directory + common::FILE_NAME_SEPARATOR + shortName; + directory + FILE_NAME_SEPARATOR + shortName; + + struct stat fileInfo = {}; - struct stat fileInfo; + if (!tryReportingError([&](std::wstring& errorMsg) -> bool + { if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks - { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(fullName) + wxT("\""); - sink.onError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - continue; - } + { + errorMsg = _("Error reading file attributes:") + "\n\"" + fullName + "\"" + "\n\n" + zen::getLastErrorFormatted(); + return false; + } + return true; + }, sink)) + continue; //ignore error: skip file const bool isSymbolicLink = S_ISLNK(fileInfo.st_mode); @@ -278,11 +352,7 @@ private: { if (::stat(fullName.c_str(), &fileInfo) != 0) //stat() resolves symlinks { - //a broken symbolic link - TraverseCallback::FileInfo details; - details.lastWriteTimeRaw = 0; //we are not interested in the modifiation time of the link - details.fileSize = 0U; - sink.onFile(shortName, fullName, details); //report broken symlink as file! + sink.onFile(shortName, fullName, TraverseCallback::FileInfo()); //report broken symlink as file! continue; } } @@ -352,7 +422,7 @@ private: const dst::RawTime encodedTime = dst::fatEncodeUtcTime(i->second); //throw (std::runtime_error) { HANDLE hTarget = ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(), - FILE_WRITE_ATTRIBUTES, + GENERIC_WRITE, //just FILE_WRITE_ATTRIBUTES may not be enough for some NAS shares! FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, @@ -410,5 +480,13 @@ private: void zen::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback& sink, DstHackCallback* dstCallback) { +#ifdef FFS_WIN + try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail) + { + zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw (FileError) + } + catch (...) {} //don't cause issues in user mode +#endif + DirTraverser(directory, followSymlinks, sink, dstCallback); } diff --git a/shared/file_traverser.h b/shared/file_traverser.h index db77f7cd..18d692df 100644 --- a/shared/file_traverser.h +++ b/shared/file_traverser.h @@ -7,7 +7,6 @@ #ifndef FILETRAVERSER_H_INCLUDED #define FILETRAVERSER_H_INCLUDED -#include <wx/string.h> #include "zstring.h" #include "loki/TypeManip.h" #include "int64.h" @@ -23,15 +22,15 @@ public: struct FileInfo { - zen::UInt64 fileSize; //unit: bytes! - zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC + UInt64 fileSize; //unit: bytes! + Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC }; struct SymlinkInfo { - zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC - Zstring targetPath; //may be empty if something goes wrong - bool dirLink; //"true": point to dir; "false": point to file (or broken Link on Linux) + Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC + Zstring targetPath; //may be empty if something goes wrong + bool dirLink; //"true": point to dir; "false": point to file (or broken Link on Linux) }; struct ReturnValDir @@ -46,14 +45,20 @@ public: ReturnValDir(Loki::Int2Type<TRAVERSING_DIR_CONTINUE>, TraverseCallback& subDirCallback) : returnCode(TRAVERSING_DIR_CONTINUE), subDirCb(&subDirCallback) {} const ReturnValueEnh returnCode; - TraverseCallback* const subDirCb; + TraverseCallback* subDirCb; + }; + + enum HandleError + { + TRAV_ERROR_RETRY, + TRAV_ERROR_IGNORE }; //overwrite these virtual methods - virtual void onError(const wxString& errorText) = 0; - virtual void onFile( const Zchar* shortName, const Zstring& fullName, const FileInfo& details) = 0; - virtual void onSymlink( const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) = 0; - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) = 0; + virtual void onFile (const Zchar* shortName, const Zstring& fullName, const FileInfo& details) = 0; + virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) = 0; + virtual ReturnValDir onDir (const Zchar* shortName, const Zstring& fullName) = 0; + virtual HandleError onError (const std::wstring& errorText) = 0; }; diff --git a/shared/global_func.cpp b/shared/global_func.cpp deleted file mode 100644 index d25f30d2..00000000 --- a/shared/global_func.cpp +++ /dev/null @@ -1,71 +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 "global_func.h" -#include "string_tools.h" -#include <wx/msgdlg.h> -#include <wx/file.h> -#include <wx/stopwatch.h> -#include "system_constants.h" - -using namespace common; -using namespace zen; - - -size_t common::getDigitCount(size_t number) //count number of digits -{ - return number == 0 ? 1 : static_cast<size_t>(::log10(static_cast<double>(number))) + 1; -} - -//############################################################################ -DebugLog::DebugLog(const wxString& filePrefix) : - prefix(filePrefix), - lineCount(0), - logFile(NULL) -{ - logFile = new wxFile; - logfileName = assembleFileName(); - logFile->Open(logfileName.c_str(), wxFile::write); -} - - -DebugLog::~DebugLog() -{ - delete logFile; //automatically closes file handle -} - - -wxString DebugLog::assembleFileName() -{ - wxString tmp = wxDateTime::Now().FormatISOTime(); - tmp.Replace(wxT(":"), wxEmptyString); - return prefix + wxString(wxT("DEBUG_")) + wxDateTime::Now().FormatISODate() + wxChar('_') + tmp + wxT(".log"); -} - - -void DebugLog::write(const wxString& logText) -{ - ++lineCount; - if (lineCount % 50000 == 0) //prevent logfile from becoming too big - { - logFile->Close(); - wxRemoveFile(logfileName); - - logfileName = assembleFileName(); - logFile->Open(logfileName.c_str(), wxFile::write); - } - - logFile->Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); - logFile->Write(logText + LINE_BREAK); -} - -//DebugLog logDebugInfo; - - -wxString getCodeLocation(const wxString& file, int line) -{ - return wxString(file).AfterLast(FILE_NAME_SEPARATOR) + wxT(", LINE ") + toString<wxString>(line) + wxT(" | "); -} diff --git a/shared/global_func.h b/shared/global_func.h index 1c6bf0ae..bf9f13dd 100644 --- a/shared/global_func.h +++ b/shared/global_func.h @@ -12,8 +12,6 @@ #include <vector> #include <set> #include <wx/string.h> -//#include <memory> -//#include <sstream> namespace common @@ -37,28 +35,8 @@ ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last //############################################################################ -class wxFile; -class DebugLog -{ -public: - wxDEPRECATED(DebugLog(const wxString& filePrefix = wxString())); - ~DebugLog(); - void write(const wxString& logText); - -private: - wxString assembleFileName(); - wxString logfileName; - wxString prefix; - int lineCount; - wxFile* logFile; //logFile.close(); <- not needed -}; -extern DebugLog logDebugInfo; -wxString getCodeLocation(const wxString& file, int line); -//small macro for writing debug information into a logfile -#define WRITE_DEBUG_LOG(x) logDebugInfo.write(getCodeLocation(__TFILE__, __LINE__) + x); -//speed alternative: wxLogDebug(wxT("text")) + DebugView @@ -78,9 +56,14 @@ wxString getCodeLocation(const wxString& file, int line); +//---------------Inline Implementation--------------------------------------------------- +inline +size_t common::getDigitCount(size_t number) //count number of digits +{ + return number == 0 ? 1 : static_cast<size_t>(::log10(static_cast<double>(number))) + 1; +} -//---------------Inline Implementation--------------------------------------------------- //Note: the following lines are a performance optimization for deleting elements from a vector: linear runtime at most! template <class T> void common::removeRowsFromVector(const std::set<size_t>& rowsToRemove, std::vector<T>& grid) @@ -126,4 +109,4 @@ ForwardIterator common::custom_binary_search(ForwardIterator first, ForwardItera return last; } -#endif // GLOBALFUNCTIONS_H_INCLUDED
\ No newline at end of file +#endif // GLOBALFUNCTIONS_H_INCLUDED diff --git a/shared/guid.cpp b/shared/guid.cpp index 5e6a64a7..1580a62d 100644 --- a/shared/guid.cpp +++ b/shared/guid.cpp @@ -10,6 +10,7 @@ //boost really should clean a bit up... #ifdef __MINGW32__ #pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wuninitialized" #endif #include <boost/uuid/uuid_generators.hpp> diff --git a/shared/i18n.cpp b/shared/i18n.cpp index 8c0e900c..f22dca56 100644 --- a/shared/i18n.cpp +++ b/shared/i18n.cpp @@ -5,7 +5,7 @@ using namespace zen; namespace { -std::auto_ptr<TranslationHandler> globalHandler; +std::unique_ptr<TranslationHandler> globalHandler; } void zen::setTranslator(TranslationHandler* newHandler) diff --git a/shared/i18n.h b/shared/i18n.h index 03456ede..cac6555c 100644 --- a/shared/i18n.h +++ b/shared/i18n.h @@ -7,8 +7,7 @@ #ifndef I18_N_HEADER_3843489325045 #define I18_N_HEADER_3843489325045 -#include <wx/string.h> -#include <vector> +#include <string> namespace zen { @@ -17,9 +16,9 @@ struct TranslationHandler { virtual ~TranslationHandler() {} - virtual wxString thousandsSeparator() = 0; - virtual wxString translate(const wxString& text) = 0; //simple translation - virtual wxString translate(const wxString& singular, const wxString& plural, int n) = 0; + virtual std::wstring thousandsSeparator() = 0; + virtual std::wstring translate(const std::wstring& text) = 0; //simple translation + virtual std::wstring translate(const std::wstring& singular, const std::wstring& plural, int n) = 0; }; void setTranslator(TranslationHandler* newHandler = NULL); //takes ownership @@ -27,26 +26,28 @@ TranslationHandler* getTranslator(); -inline wxString getThousandsSeparator() { return getTranslator() ? getTranslator()->thousandsSeparator() : wxT(","); }; +inline std::wstring getThousandsSeparator() { return getTranslator() ? getTranslator()->thousandsSeparator() : L","; }; -inline wxString translate(const wxString& text) { return getTranslator() ? getTranslator()->translate(text) : text; } +inline std::wstring translate(const std::wstring& text) { return getTranslator() ? getTranslator()->translate(text) : text; } //translate plural forms: "%x day" "%x days" //returns "%x day" if n == 1; "%x days" else for english language -inline wxString translate(const wxString& singular, const wxString& plural, int n) { return getTranslator() ? getTranslator()->translate(singular, plural, n) : n == 1 ? singular : plural; } +inline std::wstring translate(const std::wstring& singular, const std::wstring& plural, int n) { return getTranslator() ? getTranslator()->translate(singular, plural, n) : n == 1 ? singular : plural; } template <class T> inline -wxString translate(const wxString& singular, const wxString& plural, T n) +std::wstring translate(const std::wstring& singular, const std::wstring& plural, T n) { return translate(singular, plural, static_cast<int>(n % 1000000)); } } +#define CONCAT_HELPER(txt1, txt2) txt1 ## txt2 + #ifndef WXINTL_NO_GETTEXT_MACRO #error WXINTL_NO_GETTEXT_MACRO must be defined to deactivate wxWidgets underscore macro #endif -#define _(s) zen::translate(wxT(s)) -#define _P(s, p, n) zen::translate(wxT(s), wxT(p), n) +#define _(s) zen::translate(CONCAT_HELPER(L, s)) +#define _P(s, p, n) zen::translate(CONCAT_HELPER(L, s), CONCAT_HELPER(L, p), n) #endif //I18_N_HEADER_3843489325045 diff --git a/shared/inotify/CHANGELOG b/shared/inotify/CHANGELOG deleted file mode 100644 index 5c3940fa..00000000 --- a/shared/inotify/CHANGELOG +++ /dev/null @@ -1,98 +0,0 @@ -0.7.3 2009-12-09 - * cleanup of includes - -0.7.2 2007-04-18 - * added #include <stdint.h> (required for Debian Sarge, #0000155) - -0.7.1 2007-01-20 - * incorrect event name handling fixed (#0000135) - -0.7.0 2007-01-13 - * added Inotify::SetCloseOnExec() for simple setting this feature - - -0.6.3 2007-01-06 - * incorrect behavior for IN_IGNORED fixed (#0000124) - - -0.6.2 2007-01-03 - * bad IN_MOVE_SELF dumping in IN_ALL_EVENTS fixed (#0000118) - - -0.6.1 2006-12-30 - * fixed incorrect behavior for IN_ONESHOT (#0000113) - - -0.6.0 2006-12-28 - * added methods for getting/setting inotify capabilities and limits - * added IN_SELF_MOVED flag (if defined) - * added Inotify::IsRecursive() for identifying recursive watches - (will be implemented in future versions) - -0.5.3 2006-12-06 - * fixed incorrect error handling in WaitForEvents() - - -0.5.2 2006-11-12 - * problem with ignoring IN_OPEN has been fixed (#0000102) - - -0.5.1 2006-11-10 - * problems with includes have been fixed (#0000099) - - -0.5.0 2006-10-29 - * partial thread safety has been implemented (using rwlocks) - * Inotify::GetEnabledCount() method has been added - - -0.4.1 2006-10-14 - * wrong value returned by Inotify::GetWatchCount() has been fixed - (#0000092) - - -0.4.0 2006-10-13 - * two additional flags (IN_ONLYDIR and IN_DONT_FOLLOW) may be used - if available (#0000086) - * "errorneous" multiple watches on the same path are no longer - possible (#0000087) - * tarball structure has been fixed (#0000088) - * inotify-syscalls.h is included only if inotify.h doesn't contain - syscall definitions (#0000090) - * enabling/disabling is now done through watch presence in the kernel - instead of dropping events (#0000091) - * InotifyWatch::SetMask() method has been added to allow later mask - modification - - -0.3.1 2006-10-03 - * fixed: wrong behavior for EWOULDBLOCK (Inotify::WaitForEvents()) - - -0.3.0 2006-10-03 - * all errors now handled using exceptions (InotifyException) - * InotifyEvent no longer use struct inotity_event as its - internal data structure - * removed InotifyEvent::GetData() - internal data changed - * removed Inotify::IsReady() - no longer necessary - * added Inotify::GetDescriptor() - returns inotify file descriptor - * added Inotify::SetNonBlock() - switches nonblocking mode on/off - * added possibility to enable/disable watches - * some code cleanups - - -0.2.0 2006-09-15 - * InotifyEvent now contains a pointer to the source InotifyWatch - * fixed: InotifyEvent::IsType() - it now handles the mask correctly - * added a static method (InotifyEvent::GetMaskByName()) for finding a mask - for a name - * added a static version of InotifyEvent::DumpTypes() method - * added a static version of InotifyEvent::IsType() method - * dumped types (InotifyEvent::DumpTypes()) now separated by commas - instead of spaces - * InotifyEvent::DumpTypes() methods now use as general types as possible - * InotifyWatch now contains a pointer to the related Inotify - - -0.1.0 2006-09-04 -first alpha version diff --git a/shared/inotify/COPYING b/shared/inotify/COPYING deleted file mode 100644 index 17959846..00000000 --- a/shared/inotify/COPYING +++ /dev/null @@ -1,13 +0,0 @@ -inotify C++ interface - -Copyright (C) 2006, 2007, 2009 Lukas Jelinek, <lukas@aiken.cz> - -This program is free software; you can redistribute it and/or -modify it under the terms of one of the following licenses: - -1. X11 license (see LICENSE-X11) -2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) -3. GNU General Public License, version 2 (see LICENSE-GPL) - -If you want to help with choosing the best license for you, -please visit http://www.gnu.org/licenses/license-list.html. diff --git a/shared/inotify/LICENSE-GPL b/shared/inotify/LICENSE-GPL deleted file mode 100644 index a43ea212..00000000 --- a/shared/inotify/LICENSE-GPL +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/shared/inotify/LICENSE-LGPL b/shared/inotify/LICENSE-LGPL deleted file mode 100644 index 8add30ad..00000000 --- a/shared/inotify/LICENSE-LGPL +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/shared/inotify/LICENSE-X11 b/shared/inotify/LICENSE-X11 deleted file mode 100644 index c2db7930..00000000 --- a/shared/inotify/LICENSE-X11 +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2006, 2007, 2009 Lukas Jelinek - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/shared/inotify/README b/shared/inotify/README deleted file mode 100644 index 2e8e2aa2..00000000 --- a/shared/inotify/README +++ /dev/null @@ -1,70 +0,0 @@ - -inotify C++ interface - -(c) Lukas Jelinek, 2006, 2007, 2009 - -1. About -2. Requirements -3. How to use -4. Bugs, suggestions -5. Licensing -6. Documentation - - -======================================================================== - - -1. About -This program is the inotify C++ interface. It is designed for easy use -of Linux inotify technology in C++ applications. You need not to deal -with file descriptors and such uncomfortable things. Instead you can -use a few simple C++ classes. - - -2. Requirements -* Linux kernel 2.6.13 or later (with inotify compiled in) -* inotify header(s) installed in <INCLUDE_DIR>/sys. The most common - place is /usr/include/sys. Some Linux distributions contain only - inotify.h which defines everything needed. But sometimes must - be used inotify.h and inotify-syscalls.h as available e.g. at - the inotify-cxx homepage. -* GCC 4.x compiler (probably works also with GCC 3.4, possibly with - older versions too) - - -3. How to use -Include inotify-cxx.h into your sources and add inotify-cxx.cpp for -compiling (e.g. through your makefile). - -If you have installed it into your system-wide include dir (e.g. -/usr/include), use #include <inotify-cxx.h> or similar. -Otherwise use #include "inotify-cxx.h". - -For thread-safe behavior, define the INOTIFY_THREAD_SAFE symbol -(eg. -DINOTIFY_THREAD_SAFE on gcc's command line). See documentation -for details about thread safety. - - -4. Bugs, suggestions -THIS PROGRAM IS AN ALPHA VERSION. IT PROBABLY CONTAINS BUGS AND -THEREFORE IT IS NOT INTENDED FOR PRODUCTION USE. - -If you find a bug or have a suggestion how to improve the program, -please use the bug tracking system at http://bts.aiken.cz. - - -5. Licensing -This program is free software; you can redistribute it and/or -modify it under the terms of one of the following licenses: - -1. X11 license (see LICENSE-X11) -2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) -3. GNU General Public License, version 2 (see LICENSE-GPL) - -If you want to help with choosing the best license for you, -please visit http://www.gnu.org/licenses/license-list.html. - - -6. Documentation -The API reference documentation is present in the HTML and man format. -It was generated using the doxygen program. diff --git a/shared/inotify/TODO b/shared/inotify/TODO deleted file mode 100644 index 7d493c05..00000000 --- a/shared/inotify/TODO +++ /dev/null @@ -1,3 +0,0 @@ -Currently pending tasks: - -* recursive watches (for watching whole directory subtrees) diff --git a/shared/inotify/doc/html/annotated.html b/shared/inotify/doc/html/annotated.html deleted file mode 100644 index 4f67400b..00000000 --- a/shared/inotify/doc/html/annotated.html +++ /dev/null @@ -1,34 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li class="current"><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>Class List</h1>Here are the classes, structs, unions and interfaces with brief descriptions:<table> - <tr><td class="indexkey"><a class="el" href="classInotify.html">Inotify</a></td><td class="indexvalue"><a class="el" href="classInotify.html" title="inotify class">Inotify</a> class </td></tr> - <tr><td class="indexkey"><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td class="indexvalue"><a class="el" href="classInotify.html" title="inotify class">Inotify</a> event class </td></tr> - <tr><td class="indexkey"><a class="el" href="classInotifyException.html">InotifyException</a></td><td class="indexvalue">Class for inotify exceptions </td></tr> - <tr><td class="indexkey"><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td class="indexvalue"><a class="el" href="classInotify.html" title="inotify class">Inotify</a> watch class </td></tr> -</table> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotify-members.html b/shared/inotify/doc/html/classInotify-members.html deleted file mode 100644 index 3370bb6c..00000000 --- a/shared/inotify/doc/html/classInotify-members.html +++ /dev/null @@ -1,65 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Member List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>Inotify Member List</h1>This is the complete list of members for <a class="el" href="classInotify.html">Inotify</a>, including all inherited members.<p><table> - <tr class="memlist"><td><a class="el" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83">Add</a>(InotifyWatch *pWatch)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58">Add</a>(InotifyWatch &rWatch)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#86ae86c43ea1a72f562ca46393309635">Close</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#182d19b667c9e0899802b70a579eff40">FindWatch</a>(int iDescriptor)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#a4d6b9d1a9a496862febbe5bffd798c2">FindWatch</a>(const std::string &rPath)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b">GetCapability</a>(InotifyCapability_t cap)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#0233ddfe40844d729505fdfd709d22cc">GetCapabilityPath</a>(InotifyCapability_t cap)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9">GetDescriptor</a>() const </td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063">GetEnabledCount</a>() const </td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008">GetEvent</a>(InotifyEvent *pEvt)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#b028c8fa988f6bbb2ef773db3ea3a2d3">GetEvent</a>(InotifyEvent &rEvt)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#a3c533f956871f904949832ac8f5fbde">GetEventCount</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42">GetMaxEvents</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51">GetMaxInstances</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f">GetMaxWatches</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075">GetWatchCount</a>() const </td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#a6fe6e9cb3343665eb968fcd5170cfb9">Inotify</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#10880f490c33acd8bd24664fc7bce4ae">InotifyWatch</a> class</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [friend]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#eee7847efd93b681fddac56860fc7958">m_buf</a></td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">m_events</a></td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">m_fd</a></td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">m_paths</a></td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">m_watches</a></td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#19cde43d082ff92bd02654610019300d">PeekEvent</a>(InotifyEvent *pEvt)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#287dc0d238fa6edc3269441cb284f979">PeekEvent</a>(InotifyEvent &rEvt)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84">Remove</a>(InotifyWatch *pWatch)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#ac1a52b2ff6bfec07021a44e55d496a6">Remove</a>(InotifyWatch &rWatch)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#bc1fd5830ca561efb69bcd2283981741">RemoveAll</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#734538233ba2136164f76f4df6c3654e">SetCapability</a>(InotifyCapability_t cap, uint32_t val)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#124dd5816205900af61034d47ae65255">SetCloseOnExec</a>(bool fClOnEx)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9">SetMaxEvents</a>(uint32_t val)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#620c891962fe5acd26485c64e9b28d19">SetMaxInstances</a>(uint32_t val)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a">SetMaxWatches</a>(uint32_t val)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b">SetNonBlock</a>(bool fNonBlock)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b">WaitForEvents</a>(bool fNoIntr=false)</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682">~Inotify</a>()</td><td><a class="el" href="classInotify.html">Inotify</a></td><td></td></tr> -</table></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotify.html b/shared/inotify/doc/html/classInotify.html deleted file mode 100644 index 1842796c..00000000 --- a/shared/inotify/doc/html/classInotify.html +++ /dev/null @@ -1,1218 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Inotify Class Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>Inotify Class Reference</h1><!-- doxytag: class="Inotify" -->inotify class -<a href="#_details">More...</a> -<p> -<code>#include <<a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a>></code> -<p> - -<p> -<a href="classInotify-members.html">List of all members.</a><table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#a6fe6e9cb3343665eb968fcd5170cfb9">Inotify</a> () throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Constructor. <a href="#a6fe6e9cb3343665eb968fcd5170cfb9"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682">~Inotify</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Destructor. <a href="#f19dd5e491395673e4798eb9dbf5f682"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#86ae86c43ea1a72f562ca46393309635">Close</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Removes all watches and closes the inotify device. <a href="#86ae86c43ea1a72f562ca46393309635"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83">Add</a> (<a class="el" href="classInotifyWatch.html">InotifyWatch</a> *pWatch) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Adds a new watch. <a href="#2ef771ebaf982d76ebe19b3f5bc9cd83"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58">Add</a> (<a class="el" href="classInotifyWatch.html">InotifyWatch</a> &rWatch) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Adds a new watch. <a href="#35dab56d3e10bf28b5e457871adddb58"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84">Remove</a> (<a class="el" href="classInotifyWatch.html">InotifyWatch</a> *pWatch) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Removes a watch. <a href="#21c39bb8e5bbc1941b945c18f9005b84"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#ac1a52b2ff6bfec07021a44e55d496a6">Remove</a> (<a class="el" href="classInotifyWatch.html">InotifyWatch</a> &rWatch) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Removes a watch. <a href="#ac1a52b2ff6bfec07021a44e55d496a6"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#bc1fd5830ca561efb69bcd2283981741">RemoveAll</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Removes all watches. <a href="#bc1fd5830ca561efb69bcd2283981741"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075">GetWatchCount</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the count of watches. <a href="#716ae90a00dd4895709ea9b8f7959075"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063">GetEnabledCount</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the count of enabled watches. <a href="#6f432affb46f85f7bc19661d5bc77063"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b">WaitForEvents</a> (bool fNoIntr=false) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Waits for inotify events. <a href="#139c27c6643bb199619f3eae9b32e53b"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">size_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#a3c533f956871f904949832ac8f5fbde">GetEventCount</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the count of received and queued events. <a href="#a3c533f956871f904949832ac8f5fbde"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008">GetEvent</a> (<a class="el" href="classInotifyEvent.html">InotifyEvent</a> *pEvt) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Extracts a queued inotify event. <a href="#490a3f824c6d041d31ccaabe9bd92008"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#b028c8fa988f6bbb2ef773db3ea3a2d3">GetEvent</a> (<a class="el" href="classInotifyEvent.html">InotifyEvent</a> &rEvt) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Extracts a queued inotify event. <a href="#b028c8fa988f6bbb2ef773db3ea3a2d3"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#19cde43d082ff92bd02654610019300d">PeekEvent</a> (<a class="el" href="classInotifyEvent.html">InotifyEvent</a> *pEvt) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Extracts a queued inotify event (without removing). <a href="#19cde43d082ff92bd02654610019300d"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#287dc0d238fa6edc3269441cb284f979">PeekEvent</a> (<a class="el" href="classInotifyEvent.html">InotifyEvent</a> &rEvt) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Extracts a queued inotify event (without removing). <a href="#287dc0d238fa6edc3269441cb284f979"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#182d19b667c9e0899802b70a579eff40">FindWatch</a> (int iDescriptor)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Searches for a watch by a watch descriptor. <a href="#182d19b667c9e0899802b70a579eff40"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#a4d6b9d1a9a496862febbe5bffd798c2">FindWatch</a> (const std::string &rPath)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Searches for a watch by a filesystem path. <a href="#a4d6b9d1a9a496862febbe5bffd798c2"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9">GetDescriptor</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the file descriptor. <a href="#abab7015203bf36d0256e75d4f4861f9"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b">SetNonBlock</a> (bool fNonBlock) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Enables/disables non-blocking mode. <a href="#b2c8ab8ad4322fb6f0dae0eae442402b"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#124dd5816205900af61034d47ae65255">SetCloseOnExec</a> (bool fClOnEx) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Enables/disables closing on exec. <a href="#124dd5816205900af61034d47ae65255"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Static Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b">GetCapability</a> (<a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> cap) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Acquires a particular inotify capability/limit. <a href="#70b3b57e8661fbb4c5bc404b86225c3b"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#734538233ba2136164f76f4df6c3654e">SetCapability</a> (<a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> cap, uint32_t val) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Modifies a particular inotify capability/limit. <a href="#734538233ba2136164f76f4df6c3654e"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42">GetMaxEvents</a> () throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the maximum number of events in the kernel queue. <a href="#d8e4a4a87d005c71c0b5ea9c6dd53c42"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9">SetMaxEvents</a> (uint32_t val) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Sets the maximum number of events in the kernel queue. <a href="#66d90ebfa516d4bd1463749def2b58f9"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51">GetMaxInstances</a> () throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the maximum number of inotify instances per process. <a href="#c18b7732f67832260fbbd47aebb8af51"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#620c891962fe5acd26485c64e9b28d19">SetMaxInstances</a> (uint32_t val) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Sets the maximum number of inotify instances per process. <a href="#620c891962fe5acd26485c64e9b28d19"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f">GetMaxWatches</a> () throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the maximum number of inotify watches per instance. <a href="#86dae1b7a72c0d8fc2a632444a0f2f1f"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a">SetMaxWatches</a> (uint32_t val) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Sets the maximum number of inotify watches per instance. <a href="#5064380cdb4a726ab33f3fa18d15c77a"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Static Private Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static std::string </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#0233ddfe40844d729505fdfd709d22cc">GetCapabilityPath</a> (<a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> cap) throw (InotifyException)</td></tr> - -<tr><td colspan="2"><br><h2>Private Attributes</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">m_fd</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">file descriptor <a href="#95d6d0ecefff77bd3ee50f1586a4552b"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">IN_WATCH_MAP</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">m_watches</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">watches (by descriptors) <a href="#4d07f3a4412028d687936d2479d9a976"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">IN_WP_MAP</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">m_paths</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">watches (by paths) <a href="#62f275db6375a366023b2e46f73e3ecc"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">unsigned char </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#eee7847efd93b681fddac56860fc7958">m_buf</a> [INOTIFY_BUFLEN]</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">buffer for events <a href="#eee7847efd93b681fddac56860fc7958"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">std::deque< <a class="el" href="classInotifyEvent.html">InotifyEvent</a> > </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">m_events</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">event queue <a href="#0c1d6c969292dbb7c8c1283a3d8f55e0"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Friends</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html#10880f490c33acd8bd24664fc7bce4ae">InotifyWatch</a></td></tr> - -</table> -<hr><a name="_details"></a><h2>Detailed Description</h2> -inotify class -<p> -It holds information about the inotify device descriptor and manages the event queue.<p> -If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. <hr><h2>Constructor & Destructor Documentation</h2> -<a class="anchor" name="a6fe6e9cb3343665eb968fcd5170cfb9"></a><!-- doxytag: member="Inotify::Inotify" ref="a6fe6e9cb3343665eb968fcd5170cfb9" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">Inotify::Inotify </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Constructor. -<p> -Creates and initializes an instance of inotify communication object (opens the inotify device).<p> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if inotify isn't available </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="f19dd5e491395673e4798eb9dbf5f682"></a><!-- doxytag: member="Inotify::~Inotify" ref="f19dd5e491395673e4798eb9dbf5f682" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">Inotify::~Inotify </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Destructor. -<p> -Calls <a class="el" href="classInotify.html#86ae86c43ea1a72f562ca46393309635" title="Removes all watches and closes the inotify device.">Close()</a> due to clean-up. -</div> -</div><p> -<hr><h2>Member Function Documentation</h2> -<a class="anchor" name="35dab56d3e10bf28b5e457871adddb58"></a><!-- doxytag: member="Inotify::Add" ref="35dab56d3e10bf28b5e457871adddb58" args="(InotifyWatch &rWatch)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::Add </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> & </td> - <td class="paramname"> <em>rWatch</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Adds a new watch. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rWatch</em> </td><td>inotify watch</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if adding failed </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="2ef771ebaf982d76ebe19b3f5bc9cd83"></a><!-- doxytag: member="Inotify::Add" ref="2ef771ebaf982d76ebe19b3f5bc9cd83" args="(InotifyWatch *pWatch)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::Add </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td> - <td class="paramname"> <em>pWatch</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Adds a new watch. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>pWatch</em> </td><td>inotify watch</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if adding failed </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.png" border="0" usemap="#classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph_map" alt=""></center> -<map name="classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph_map"> -<area shape="rect" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="143,5,228,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="86ae86c43ea1a72f562ca46393309635"></a><!-- doxytag: member="Inotify::Close" ref="86ae86c43ea1a72f562ca46393309635" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::Close </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Removes all watches and closes the inotify device. -<p> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.png" border="0" usemap="#classInotify_86ae86c43ea1a72f562ca46393309635_icgraph_map" alt=""></center> -<map name="classInotify_86ae86c43ea1a72f562ca46393309635_icgraph_map"> -<area shape="rect" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682" title="Destructor." alt="" coords="151,5,255,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="a4d6b9d1a9a496862febbe5bffd798c2"></a><!-- doxytag: member="Inotify::FindWatch" ref="a4d6b9d1a9a496862febbe5bffd798c2" args="(const std::string &rPath)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * Inotify::FindWatch </td> - <td>(</td> - <td class="paramtype">const std::string & </td> - <td class="paramname"> <em>rPath</em> </td> - <td> ) </td> - <td></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Searches for a watch by a filesystem path. -<p> -It tries to find a watch by the given filesystem path.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rPath</em> </td><td>filesystem path </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>pointer to a watch; NULL if no such watch exists</dd></dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>The path must be exactly identical to the one used for the searched watch. Be careful about absolute/relative and case-insensitive paths. </dd></dl> - -</div> -</div><p> -<a class="anchor" name="182d19b667c9e0899802b70a579eff40"></a><!-- doxytag: member="Inotify::FindWatch" ref="182d19b667c9e0899802b70a579eff40" args="(int iDescriptor)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * Inotify::FindWatch </td> - <td>(</td> - <td class="paramtype">int </td> - <td class="paramname"> <em>iDescriptor</em> </td> - <td> ) </td> - <td></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Searches for a watch by a watch descriptor. -<p> -It tries to find a watch by the given descriptor.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>iDescriptor</em> </td><td>watch descriptor </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>pointer to a watch; NULL if no such watch exists </dd></dl> - -</div> -</div><p> -<a class="anchor" name="70b3b57e8661fbb4c5bc404b86225c3b"></a><!-- doxytag: member="Inotify::GetCapability" ref="70b3b57e8661fbb4c5bc404b86225c3b" args="(InotifyCapability_t cap)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t Inotify::GetCapability </td> - <td>(</td> - <td class="paramtype"><a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> </td> - <td class="paramname"> <em>cap</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Acquires a particular inotify capability/limit. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>cap</em> </td><td>capability/limit identifier </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>capability/limit value </dd></dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be acquired </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.png" border="0" usemap="#classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph_map" alt=""></center> -<map name="classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph_map"> -<area shape="rect" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42" title="Returns the maximum number of events in the kernel queue." alt="" coords="204,5,351,32"><area shape="rect" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51" title="Returns the maximum number of inotify instances per process." alt="" coords="195,56,360,83"><area shape="rect" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f" title="Returns the maximum number of inotify watches per instance." alt="" coords="197,107,357,133"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="0233ddfe40844d729505fdfd709d22cc"></a><!-- doxytag: member="Inotify::GetCapabilityPath" ref="0233ddfe40844d729505fdfd709d22cc" args="(InotifyCapability_t cap)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">std::string Inotify::GetCapabilityPath </td> - <td>(</td> - <td class="paramtype"><a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> </td> - <td class="paramname"> <em>cap</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [static, private]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="abab7015203bf36d0256e75d4f4861f9"></a><!-- doxytag: member="Inotify::GetDescriptor" ref="abab7015203bf36d0256e75d4f4861f9" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int Inotify::GetDescriptor </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the file descriptor. -<p> -The descriptor can be used in standard low-level file functions (poll(), select(), fcntl() etc.).<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>valid file descriptor or -1 for inactive object</dd></dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b" title="Enables/disables non-blocking mode.">SetNonBlock()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="6f432affb46f85f7bc19661d5bc77063"></a><!-- doxytag: member="Inotify::GetEnabledCount" ref="6f432affb46f85f7bc19661d5bc77063" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">size_t Inotify::GetEnabledCount </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the count of enabled watches. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>count of enabled watches</dd></dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075" title="Returns the count of watches.">GetWatchCount()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="b028c8fa988f6bbb2ef773db3ea3a2d3"></a><!-- doxytag: member="Inotify::GetEvent" ref="b028c8fa988f6bbb2ef773db3ea3a2d3" args="(InotifyEvent &rEvt)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool Inotify::GetEvent </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyEvent.html">InotifyEvent</a> & </td> - <td class="paramname"> <em>rEvt</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Extracts a queued inotify event. -<p> -The extracted event is removed from the queue.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in,out]</tt> </td><td valign="top"><em>rEvt</em> </td><td>event object</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown only in very anomalous cases </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="490a3f824c6d041d31ccaabe9bd92008"></a><!-- doxytag: member="Inotify::GetEvent" ref="490a3f824c6d041d31ccaabe9bd92008" args="(InotifyEvent *pEvt)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool Inotify::GetEvent </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyEvent.html">InotifyEvent</a> * </td> - <td class="paramname"> <em>pEvt</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Extracts a queued inotify event. -<p> -The extracted event is removed from the queue. If the pointer is NULL it does nothing.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in,out]</tt> </td><td valign="top"><em>pEvt</em> </td><td>event object</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the provided pointer is NULL </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.png" border="0" usemap="#classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph_map" alt=""></center> -<map name="classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph_map"> -<area shape="rect" href="classInotify.html#b028c8fa988f6bbb2ef773db3ea3a2d3" title="Extracts a queued inotify event." alt="" coords="172,5,287,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="a3c533f956871f904949832ac8f5fbde"></a><!-- doxytag: member="Inotify::GetEventCount" ref="a3c533f956871f904949832ac8f5fbde" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">size_t Inotify::GetEventCount </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the count of received and queued events. -<p> -This number is related to the events in the queue inside this object, not to the events pending in the kernel.<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>count of events </dd></dl> - -</div> -</div><p> -<a class="anchor" name="d8e4a4a87d005c71c0b5ea9c6dd53c42"></a><!-- doxytag: member="Inotify::GetMaxEvents" ref="d8e4a4a87d005c71c0b5ea9c6dd53c42" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static uint32_t Inotify::GetMaxEvents </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the maximum number of events in the kernel queue. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>maximum number of events in the kernel queue </dd></dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be acquired </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="c18b7732f67832260fbbd47aebb8af51"></a><!-- doxytag: member="Inotify::GetMaxInstances" ref="c18b7732f67832260fbbd47aebb8af51" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static uint32_t Inotify::GetMaxInstances </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the maximum number of inotify instances per process. -<p> -It means the maximum number of open inotify file descriptors per running process.<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>maximum number of inotify instances </dd></dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be acquired </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="86dae1b7a72c0d8fc2a632444a0f2f1f"></a><!-- doxytag: member="Inotify::GetMaxWatches" ref="86dae1b7a72c0d8fc2a632444a0f2f1f" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static uint32_t Inotify::GetMaxWatches </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the maximum number of inotify watches per instance. -<p> -It means the maximum number of inotify watches per inotify file descriptor.<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>maximum number of inotify watches </dd></dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be acquired </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="716ae90a00dd4895709ea9b8f7959075"></a><!-- doxytag: member="Inotify::GetWatchCount" ref="716ae90a00dd4895709ea9b8f7959075" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">size_t Inotify::GetWatchCount </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the count of watches. -<p> -This is the total count of all watches (regardless whether enabled or not).<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>count of watches</dd></dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063" title="Returns the count of enabled watches.">GetEnabledCount()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="287dc0d238fa6edc3269441cb284f979"></a><!-- doxytag: member="Inotify::PeekEvent" ref="287dc0d238fa6edc3269441cb284f979" args="(InotifyEvent &rEvt)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool Inotify::PeekEvent </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyEvent.html">InotifyEvent</a> & </td> - <td class="paramname"> <em>rEvt</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Extracts a queued inotify event (without removing). -<p> -The extracted event stays in the queue.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in,out]</tt> </td><td valign="top"><em>rEvt</em> </td><td>event object</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown only in very anomalous cases </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="19cde43d082ff92bd02654610019300d"></a><!-- doxytag: member="Inotify::PeekEvent" ref="19cde43d082ff92bd02654610019300d" args="(InotifyEvent *pEvt)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool Inotify::PeekEvent </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyEvent.html">InotifyEvent</a> * </td> - <td class="paramname"> <em>pEvt</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Extracts a queued inotify event (without removing). -<p> -The extracted event stays in the queue. If the pointer is NULL it does nothing.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in,out]</tt> </td><td valign="top"><em>pEvt</em> </td><td>event object</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the provided pointer is NULL </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_19cde43d082ff92bd02654610019300d_icgraph.png" border="0" usemap="#classInotify_19cde43d082ff92bd02654610019300d_icgraph_map" alt=""></center> -<map name="classInotify_19cde43d082ff92bd02654610019300d_icgraph_map"> -<area shape="rect" href="classInotify.html#287dc0d238fa6edc3269441cb284f979" title="Extracts a queued inotify event (without removing)." alt="" coords="179,5,304,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="ac1a52b2ff6bfec07021a44e55d496a6"></a><!-- doxytag: member="Inotify::Remove" ref="ac1a52b2ff6bfec07021a44e55d496a6" args="(InotifyWatch &rWatch)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::Remove </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> & </td> - <td class="paramname"> <em>rWatch</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Removes a watch. -<p> -If the given watch is not present it does nothing.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rWatch</em> </td><td>inotify watch</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if removing failed </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="21c39bb8e5bbc1941b945c18f9005b84"></a><!-- doxytag: member="Inotify::Remove" ref="21c39bb8e5bbc1941b945c18f9005b84" args="(InotifyWatch *pWatch)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::Remove </td> - <td>(</td> - <td class="paramtype"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td> - <td class="paramname"> <em>pWatch</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Removes a watch. -<p> -If the given watch is not present it does nothing.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>pWatch</em> </td><td>inotify watch</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if removing failed </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.png" border="0" usemap="#classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph_map" alt=""></center> -<map name="classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph_map"> -<area shape="rect" href="classInotify.html#ac1a52b2ff6bfec07021a44e55d496a6" title="Removes a watch." alt="" coords="163,5,272,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="bc1fd5830ca561efb69bcd2283981741"></a><!-- doxytag: member="Inotify::RemoveAll" ref="bc1fd5830ca561efb69bcd2283981741" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::RemoveAll </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Removes all watches. -<p> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.png" border="0" usemap="#classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph_map" alt=""></center> -<map name="classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph_map"> -<area shape="rect" href="classInotify.html#86ae86c43ea1a72f562ca46393309635" title="Removes all watches and closes the inotify device." alt="" coords="179,5,275,32"><area shape="rect" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682" title="Destructor." alt="" coords="324,5,428,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="734538233ba2136164f76f4df6c3654e"></a><!-- doxytag: member="Inotify::SetCapability" ref="734538233ba2136164f76f4df6c3654e" args="(InotifyCapability_t cap, uint32_t val)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::SetCapability </td> - <td>(</td> - <td class="paramtype"><a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> </td> - <td class="paramname"> <em>cap</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>val</em></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Modifies a particular inotify capability/limit. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>cap</em> </td><td>capability/limit identifier </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>val</em> </td><td>new capability/limit value </td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be set </td></tr> - </table> -</dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>Using this function requires root privileges. Beware of setting extensive values - it may seriously affect system performance and/or stability. </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotify_734538233ba2136164f76f4df6c3654e_icgraph.png" border="0" usemap="#classInotify_734538233ba2136164f76f4df6c3654e_icgraph_map" alt=""></center> -<map name="classInotify_734538233ba2136164f76f4df6c3654e_icgraph_map"> -<area shape="rect" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9" title="Sets the maximum number of events in the kernel queue." alt="" coords="204,5,351,32"><area shape="rect" href="classInotify.html#620c891962fe5acd26485c64e9b28d19" title="Sets the maximum number of inotify instances per process." alt="" coords="196,56,359,83"><area shape="rect" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a" title="Sets the maximum number of inotify watches per instance." alt="" coords="197,107,357,133"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="124dd5816205900af61034d47ae65255"></a><!-- doxytag: member="Inotify::SetCloseOnExec" ref="124dd5816205900af61034d47ae65255" args="(bool fClOnEx)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::SetCloseOnExec </td> - <td>(</td> - <td class="paramtype">bool </td> - <td class="paramname"> <em>fClOnEx</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Enables/disables closing on exec. -<p> -Enable this if you want to close the descriptor when executing another program. Otherwise, the descriptor will be inherited.<p> -Closing on exec is disabled by default.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>fClOnEx</em> </td><td>enable/disable closing on exec</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if setting failed</td></tr> - </table> -</dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9" title="Returns the file descriptor.">GetDescriptor()</a>, <a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b" title="Enables/disables non-blocking mode.">SetNonBlock()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="66d90ebfa516d4bd1463749def2b58f9"></a><!-- doxytag: member="Inotify::SetMaxEvents" ref="66d90ebfa516d4bd1463749def2b58f9" args="(uint32_t val)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static void Inotify::SetMaxEvents </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>val</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Sets the maximum number of events in the kernel queue. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>val</em> </td><td>new value </td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be set </td></tr> - </table> -</dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. </dd></dl> - -</div> -</div><p> -<a class="anchor" name="620c891962fe5acd26485c64e9b28d19"></a><!-- doxytag: member="Inotify::SetMaxInstances" ref="620c891962fe5acd26485c64e9b28d19" args="(uint32_t val)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static void Inotify::SetMaxInstances </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>val</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Sets the maximum number of inotify instances per process. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>val</em> </td><td>new value </td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be set </td></tr> - </table> -</dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. </dd></dl> - -</div> -</div><p> -<a class="anchor" name="5064380cdb4a726ab33f3fa18d15c77a"></a><!-- doxytag: member="Inotify::SetMaxWatches" ref="5064380cdb4a726ab33f3fa18d15c77a" args="(uint32_t val)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static void Inotify::SetMaxWatches </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>val</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)<code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Sets the maximum number of inotify watches per instance. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>val</em> </td><td>new value </td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if the given value cannot be set </td></tr> - </table> -</dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. </dd></dl> - -</div> -</div><p> -<a class="anchor" name="b2c8ab8ad4322fb6f0dae0eae442402b"></a><!-- doxytag: member="Inotify::SetNonBlock" ref="b2c8ab8ad4322fb6f0dae0eae442402b" args="(bool fNonBlock)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::SetNonBlock </td> - <td>(</td> - <td class="paramtype">bool </td> - <td class="paramname"> <em>fNonBlock</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Enables/disables non-blocking mode. -<p> -Use this mode if you want to monitor the descriptor (acquired thru <a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9" title="Returns the file descriptor.">GetDescriptor()</a>) in functions such as poll(), select() etc.<p> -Non-blocking mode is disabled by default.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>fNonBlock</em> </td><td>enable/disable non-blocking mode</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if setting mode failed</td></tr> - </table> -</dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9" title="Returns the file descriptor.">GetDescriptor()</a>, <a class="el" href="classInotify.html#124dd5816205900af61034d47ae65255" title="Enables/disables closing on exec.">SetCloseOnExec()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="139c27c6643bb199619f3eae9b32e53b"></a><!-- doxytag: member="Inotify::WaitForEvents" ref="139c27c6643bb199619f3eae9b32e53b" args="(bool fNoIntr=false)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void Inotify::WaitForEvents </td> - <td>(</td> - <td class="paramtype">bool </td> - <td class="paramname"> <em>fNoIntr</em> = <code>false</code> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Waits for inotify events. -<p> -It waits until one or more events occur. When called in nonblocking mode it only retrieves occurred events to the internal queue and exits.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>fNoIntr</em> </td><td>if true it re-calls the system call after a handled signal</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if reading events failed</td></tr> - </table> -</dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b" title="Enables/disables non-blocking mode.">SetNonBlock()</a> </dd></dl> - -</div> -</div><p> -<hr><h2>Friends And Related Function Documentation</h2> -<a class="anchor" name="10880f490c33acd8bd24664fc7bce4ae"></a><!-- doxytag: member="Inotify::InotifyWatch" ref="10880f490c33acd8bd24664fc7bce4ae" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">friend class <a class="el" href="classInotifyWatch.html">InotifyWatch</a><code> [friend]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<hr><h2>Member Data Documentation</h2> -<a class="anchor" name="eee7847efd93b681fddac56860fc7958"></a><!-- doxytag: member="Inotify::m_buf" ref="eee7847efd93b681fddac56860fc7958" args="[INOTIFY_BUFLEN]" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">unsigned char <a class="el" href="classInotify.html#eee7847efd93b681fddac56860fc7958">Inotify::m_buf</a>[INOTIFY_BUFLEN]<code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -buffer for events -<p> - -</div> -</div><p> -<a class="anchor" name="0c1d6c969292dbb7c8c1283a3d8f55e0"></a><!-- doxytag: member="Inotify::m_events" ref="0c1d6c969292dbb7c8c1283a3d8f55e0" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">std::deque<<a class="el" href="classInotifyEvent.html">InotifyEvent</a>> <a class="el" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">Inotify::m_events</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -event queue -<p> - -</div> -</div><p> -<a class="anchor" name="95d6d0ecefff77bd3ee50f1586a4552b"></a><!-- doxytag: member="Inotify::m_fd" ref="95d6d0ecefff77bd3ee50f1586a4552b" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int <a class="el" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">Inotify::m_fd</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -file descriptor -<p> - -</div> -</div><p> -<a class="anchor" name="62f275db6375a366023b2e46f73e3ecc"></a><!-- doxytag: member="Inotify::m_paths" ref="62f275db6375a366023b2e46f73e3ecc" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">IN_WP_MAP</a> <a class="el" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">Inotify::m_paths</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -watches (by paths) -<p> - -</div> -</div><p> -<a class="anchor" name="4d07f3a4412028d687936d2479d9a976"></a><!-- doxytag: member="Inotify::m_watches" ref="4d07f3a4412028d687936d2479d9a976" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">IN_WATCH_MAP</a> <a class="el" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">Inotify::m_watches</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -watches (by descriptors) -<p> - -</div> -</div><p> -<hr>The documentation for this class was generated from the following files:<ul> -<li><a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a><li><a class="el" href="inotify-cxx_8cpp.html">inotify-cxx.cpp</a></ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyEvent-members.html b/shared/inotify/doc/html/classInotifyEvent-members.html deleted file mode 100644 index 6b7bcc31..00000000 --- a/shared/inotify/doc/html/classInotifyEvent-members.html +++ /dev/null @@ -1,48 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Member List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyEvent Member List</h1>This is the complete list of members for <a class="el" href="classInotifyEvent.html">InotifyEvent</a>, including all inherited members.<p><table> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5">DumpTypes</a>(uint32_t uValue, std::string &rStr)</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea">DumpTypes</a>(std::string &rStr) const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17">GetCookie</a>() const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341">GetDescriptor</a>() const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a">GetLength</a>() const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f">GetMask</a>() const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#eced3a88a6dea190c5df19c2a6599010">GetMaskByName</a>(const std::string &rName)</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097">GetName</a>() const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f">GetName</a>(std::string &rName) const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92">GetWatch</a>()</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046">InotifyEvent</a>()</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#6d7f3fc0f51580da4a3ec2348609df64">InotifyEvent</a>(const struct inotify_event *pEvt, InotifyWatch *pWatch)</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb">IsType</a>(uint32_t uValue, uint32_t uType)</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline, static]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#477ae71116ec393434a1f62a7170a156">IsType</a>(uint32_t uType) const </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">m_name</a></td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">m_pWatch</a></td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">m_uCookie</a></td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">m_uMask</a></td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888">~InotifyEvent</a>()</td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td><td><code> [inline]</code></td></tr> -</table></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyEvent.html b/shared/inotify/doc/html/classInotifyEvent.html deleted file mode 100644 index ccc3c517..00000000 --- a/shared/inotify/doc/html/classInotifyEvent.html +++ /dev/null @@ -1,617 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: InotifyEvent Class Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyEvent Class Reference</h1><!-- doxytag: class="InotifyEvent" -->inotify event class -<a href="#_details">More...</a> -<p> -<code>#include <<a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a>></code> -<p> -<div class="dynheader"> -Collaboration diagram for InotifyEvent:</div> -<div class="dynsection"> -<p><center><img src="classInotifyEvent__coll__graph.png" border="0" usemap="#InotifyEvent__coll__map" alt="Collaboration graph"></center> -<map name="InotifyEvent__coll__map"> -<area shape="rect" href="classInotifyWatch.html" title="inotify watch class" alt="" coords="5,96,99,123"><area shape="rect" href="classInotify.html" title="inotify class" alt="" coords="24,5,80,32"></map> -<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center></div> - -<p> -<a href="classInotifyEvent-members.html">List of all members.</a><table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046">InotifyEvent</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Constructor. <a href="#f416dbbd4e6ddd3c0eea6cb540f0b046"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#6d7f3fc0f51580da4a3ec2348609df64">InotifyEvent</a> (const struct inotify_event *pEvt, <a class="el" href="classInotifyWatch.html">InotifyWatch</a> *pWatch)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Constructor. <a href="#6d7f3fc0f51580da4a3ec2348609df64"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888">~InotifyEvent</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Destructor. <a href="#a48030da1d3a1b1741ca791c9e129888"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341">GetDescriptor</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the event watch descriptor. <a href="#463aacc1f660fbc1c39108feb2601341"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f">GetMask</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the event mask. <a href="#c7160544f6f4f24611df57a4422ac47f"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#477ae71116ec393434a1f62a7170a156">IsType</a> (uint32_t uType) const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Checks for the event type. <a href="#477ae71116ec393434a1f62a7170a156"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17">GetCookie</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the event cookie. <a href="#7e65e49f7d0f11c71442e31d688e4b17"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a">GetLength</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the event name length. <a href="#30c8c2e1e490b8968ab9cb3364fe579a"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">const std::string & </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097">GetName</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the event name. <a href="#5ab91d587bdc7ab3c18c6cdff73f3097"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f">GetName</a> (std::string &rName) const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Extracts the event name. <a href="#3aea2437ba8553be703d91b45247a68f"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92">GetWatch</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the source watch. <a href="#979cd46f53ed674331a5a6d47d1cde92"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea">DumpTypes</a> (std::string &rStr) const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Fills the string with all types contained in the event mask. <a href="#3e5d18ff8dea01d14286e4b44a2b76ea"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Static Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb">IsType</a> (uint32_t uValue, uint32_t uType)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Checks a value for the event type. <a href="#309ebf3c5b131522295185a926d551bb"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#eced3a88a6dea190c5df19c2a6599010">GetMaskByName</a> (const std::string &rName)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Finds the appropriate mask for a name. <a href="#eced3a88a6dea190c5df19c2a6599010"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5">DumpTypes</a> (uint32_t uValue, std::string &rStr)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Fills the string with all types contained in an event mask value. <a href="#c08a0a26ea33dbe94aaf1ac830c103a5"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Private Attributes</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">m_uMask</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">mask <a href="#739a943357af0c3fafd58466803e04fa"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">m_uCookie</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">cookie <a href="#bf417d466fb0173d337cc66539ee55af"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">std::string </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">m_name</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">name <a href="#6c507a3466515aedc266bdc267079604"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">m_pWatch</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">source watch <a href="#2d151cdcc547ee4ce49cfd44328d87ac"></a><br></td></tr> -</table> -<hr><a name="_details"></a><h2>Detailed Description</h2> -inotify event class -<p> -It holds all information about inotify event and provides access to its particular values.<p> -This class is not (and is not intended to be) thread-safe and therefore it must not be used concurrently in multiple threads. <hr><h2>Constructor & Destructor Documentation</h2> -<a class="anchor" name="f416dbbd4e6ddd3c0eea6cb540f0b046"></a><!-- doxytag: member="InotifyEvent::InotifyEvent" ref="f416dbbd4e6ddd3c0eea6cb540f0b046" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyEvent::InotifyEvent </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Constructor. -<p> -Creates a plain event. -</div> -</div><p> -<a class="anchor" name="6d7f3fc0f51580da4a3ec2348609df64"></a><!-- doxytag: member="InotifyEvent::InotifyEvent" ref="6d7f3fc0f51580da4a3ec2348609df64" args="(const struct inotify_event *pEvt, InotifyWatch *pWatch)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyEvent::InotifyEvent </td> - <td>(</td> - <td class="paramtype">const struct inotify_event * </td> - <td class="paramname"> <em>pEvt</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype"><a class="el" href="classInotifyWatch.html">InotifyWatch</a> * </td> - <td class="paramname"> <em>pWatch</em></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Constructor. -<p> -Creates an event based on inotify event data. For NULL pointers it works the same way as <a class="el" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046" title="Constructor.">InotifyEvent()</a>.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>pEvt</em> </td><td>event data </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>pWatch</em> </td><td>inotify watch </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="a48030da1d3a1b1741ca791c9e129888"></a><!-- doxytag: member="InotifyEvent::~InotifyEvent" ref="a48030da1d3a1b1741ca791c9e129888" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyEvent::~InotifyEvent </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Destructor. -<p> - -</div> -</div><p> -<hr><h2>Member Function Documentation</h2> -<a class="anchor" name="3e5d18ff8dea01d14286e4b44a2b76ea"></a><!-- doxytag: member="InotifyEvent::DumpTypes" ref="3e5d18ff8dea01d14286e4b44a2b76ea" args="(std::string &rStr) const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyEvent::DumpTypes </td> - <td>(</td> - <td class="paramtype">std::string & </td> - <td class="paramname"> <em>rStr</em> </td> - <td> ) </td> - <td> const</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Fills the string with all types contained in the event mask. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[out]</tt> </td><td valign="top"><em>rStr</em> </td><td>dumped event types </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="c08a0a26ea33dbe94aaf1ac830c103a5"></a><!-- doxytag: member="InotifyEvent::DumpTypes" ref="c08a0a26ea33dbe94aaf1ac830c103a5" args="(uint32_t uValue, std::string &rStr)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyEvent::DumpTypes </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>uValue</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">std::string & </td> - <td class="paramname"> <em>rStr</em></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td><code> [static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Fills the string with all types contained in an event mask value. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uValue</em> </td><td>event mask value </td></tr> - <tr><td valign="top"><tt>[out]</tt> </td><td valign="top"><em>rStr</em> </td><td>dumped event types </td></tr> - </table> -</dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.png" border="0" usemap="#classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph_map" alt=""></center> -<map name="classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph_map"> -<area shape="rect" href="classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea" title="Fills the string with all types contained in the event mask." alt="" coords="220,5,383,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="7e65e49f7d0f11c71442e31d688e4b17"></a><!-- doxytag: member="InotifyEvent::GetCookie" ref="7e65e49f7d0f11c71442e31d688e4b17" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t InotifyEvent::GetCookie </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the event cookie. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>event cookie </dd></dl> - -</div> -</div><p> -<a class="anchor" name="463aacc1f660fbc1c39108feb2601341"></a><!-- doxytag: member="InotifyEvent::GetDescriptor" ref="463aacc1f660fbc1c39108feb2601341" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int32_t InotifyEvent::GetDescriptor </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the event watch descriptor. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>watch descriptor</dd></dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59" title="Returns the watch descriptor.">InotifyWatch::GetDescriptor()</a> </dd></dl> - -</div> -</div><p> -<a class="anchor" name="30c8c2e1e490b8968ab9cb3364fe579a"></a><!-- doxytag: member="InotifyEvent::GetLength" ref="30c8c2e1e490b8968ab9cb3364fe579a" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t InotifyEvent::GetLength </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the event name length. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>event name length </dd></dl> - -</div> -</div><p> -<a class="anchor" name="c7160544f6f4f24611df57a4422ac47f"></a><!-- doxytag: member="InotifyEvent::GetMask" ref="c7160544f6f4f24611df57a4422ac47f" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t InotifyEvent::GetMask </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the event mask. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>event mask</dd></dl> -<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009" title="Returns the watch event mask.">InotifyWatch::GetMask()</a> </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.png" border="0" usemap="#classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph_map" alt=""></center> -<map name="classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph_map"> -<area shape="rect" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="204,5,351,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="eced3a88a6dea190c5df19c2a6599010"></a><!-- doxytag: member="InotifyEvent::GetMaskByName" ref="eced3a88a6dea190c5df19c2a6599010" args="(const std::string &rName)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t InotifyEvent::GetMaskByName </td> - <td>(</td> - <td class="paramtype">const std::string & </td> - <td class="paramname"> <em>rName</em> </td> - <td> ) </td> - <td><code> [static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Finds the appropriate mask for a name. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rName</em> </td><td>mask name </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>mask for name; 0 on failure </dd></dl> - -</div> -</div><p> -<a class="anchor" name="3aea2437ba8553be703d91b45247a68f"></a><!-- doxytag: member="InotifyEvent::GetName" ref="3aea2437ba8553be703d91b45247a68f" args="(std::string &rName) const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyEvent::GetName </td> - <td>(</td> - <td class="paramtype">std::string & </td> - <td class="paramname"> <em>rName</em> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Extracts the event name. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[out]</tt> </td><td valign="top"><em>rName</em> </td><td>event name </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="5ab91d587bdc7ab3c18c6cdff73f3097"></a><!-- doxytag: member="InotifyEvent::GetName" ref="5ab91d587bdc7ab3c18c6cdff73f3097" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">const std::string& InotifyEvent::GetName </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the event name. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>event name </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.png" border="0" usemap="#classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph_map" alt=""></center> -<map name="classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph_map"> -<area shape="rect" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f" title="Extracts the event name." alt="" coords="207,5,356,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="979cd46f53ed674331a5a6d47d1cde92"></a><!-- doxytag: member="InotifyEvent::GetWatch" ref="979cd46f53ed674331a5a6d47d1cde92" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotifyWatch.html">InotifyWatch</a>* InotifyEvent::GetWatch </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the source watch. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>source watch </dd></dl> - -</div> -</div><p> -<a class="anchor" name="477ae71116ec393434a1f62a7170a156"></a><!-- doxytag: member="InotifyEvent::IsType" ref="477ae71116ec393434a1f62a7170a156" args="(uint32_t uType) const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool InotifyEvent::IsType </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>uType</em> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Checks for the event type. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uType</em> </td><td>type which is checked for </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>true = event mask contains the given type, false = otherwise </dd></dl> - -</div> -</div><p> -<a class="anchor" name="309ebf3c5b131522295185a926d551bb"></a><!-- doxytag: member="InotifyEvent::IsType" ref="309ebf3c5b131522295185a926d551bb" args="(uint32_t uValue, uint32_t uType)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">static bool InotifyEvent::IsType </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>uValue</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>uType</em></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td><code> [inline, static]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Checks a value for the event type. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uValue</em> </td><td>checked value </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uType</em> </td><td>type which is checked for </td></tr> - </table> -</dl> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>true = the value contains the given type, false = otherwise </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.png" border="0" usemap="#classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph_map" alt=""></center> -<map name="classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph_map"> -<area shape="rect" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5" title="Fills the string with all types contained in an event mask value." alt="" coords="188,5,351,32"><area shape="rect" href="classInotifyEvent.html#477ae71116ec393434a1f62a7170a156" title="Checks for the event type." alt="" coords="203,56,336,83"><area shape="rect" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="196,107,343,133"><area shape="rect" href="classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea" title="Fills the string with all types contained in the event mask." alt="" coords="401,5,564,32"></map> -</div> - -</div> -</div><p> -<hr><h2>Member Data Documentation</h2> -<a class="anchor" name="6c507a3466515aedc266bdc267079604"></a><!-- doxytag: member="InotifyEvent::m_name" ref="6c507a3466515aedc266bdc267079604" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">std::string <a class="el" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">InotifyEvent::m_name</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -name -<p> - -</div> -</div><p> -<a class="anchor" name="2d151cdcc547ee4ce49cfd44328d87ac"></a><!-- doxytag: member="InotifyEvent::m_pWatch" ref="2d151cdcc547ee4ce49cfd44328d87ac" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotifyWatch.html">InotifyWatch</a>* <a class="el" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">InotifyEvent::m_pWatch</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -source watch -<p> - -</div> -</div><p> -<a class="anchor" name="bf417d466fb0173d337cc66539ee55af"></a><!-- doxytag: member="InotifyEvent::m_uCookie" ref="bf417d466fb0173d337cc66539ee55af" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t <a class="el" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">InotifyEvent::m_uCookie</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -cookie -<p> - -</div> -</div><p> -<a class="anchor" name="739a943357af0c3fafd58466803e04fa"></a><!-- doxytag: member="InotifyEvent::m_uMask" ref="739a943357af0c3fafd58466803e04fa" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t <a class="el" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">InotifyEvent::m_uMask</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -mask -<p> - -</div> -</div><p> -<hr>The documentation for this class was generated from the following files:<ul> -<li><a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a><li><a class="el" href="inotify-cxx_8cpp.html">inotify-cxx.cpp</a></ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.map b/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.map deleted file mode 100644 index e31ea0ca..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.map +++ /dev/null @@ -1,4 +0,0 @@ -<area shape="rect" href="$classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5" title="Fills the string with all types contained in an event mask value." alt="" coords="188,5,351,32"> -<area shape="rect" href="$classInotifyEvent.html#477ae71116ec393434a1f62a7170a156" title="Checks for the event type." alt="" coords="203,56,336,83"> -<area shape="rect" href="$classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="196,107,343,133"> -<area shape="rect" href="$classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea" title="Fills the string with all types contained in the event mask." alt="" coords="401,5,564,32"> diff --git a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.md5 b/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.md5 deleted file mode 100644 index c108d32f..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -80a24dfdb3ffd06ee1dfd925cc6feb7e
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.png b/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.png Binary files differdeleted file mode 100644 index 72a734da..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_309ebf3c5b131522295185a926d551bb_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.map b/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.map deleted file mode 100644 index 61683c0b..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f" title="Extracts the event name." alt="" coords="207,5,356,32"> diff --git a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.md5 b/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.md5 deleted file mode 100644 index 390b7f98..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -eeb67887bd904a352d248b3a661c09ac
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.png b/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.png Binary files differdeleted file mode 100644 index 66409056..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_5ab91d587bdc7ab3c18c6cdff73f3097_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyEvent__coll__graph.map b/shared/inotify/doc/html/classInotifyEvent__coll__graph.map deleted file mode 100644 index fc3ab859..00000000 --- a/shared/inotify/doc/html/classInotifyEvent__coll__graph.map +++ /dev/null @@ -1,2 +0,0 @@ -<area shape="rect" href="$classInotifyWatch.html" title="inotify watch class" alt="" coords="5,96,99,123"> -<area shape="rect" href="$classInotify.html" title="inotify class" alt="" coords="24,5,80,32"> diff --git a/shared/inotify/doc/html/classInotifyEvent__coll__graph.md5 b/shared/inotify/doc/html/classInotifyEvent__coll__graph.md5 deleted file mode 100644 index 6d1a7d05..00000000 --- a/shared/inotify/doc/html/classInotifyEvent__coll__graph.md5 +++ /dev/null @@ -1 +0,0 @@ -10fc9c98fa3b1e02aafb36817e9e1285
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyEvent__coll__graph.png b/shared/inotify/doc/html/classInotifyEvent__coll__graph.png Binary files differdeleted file mode 100644 index 8c7ee763..00000000 --- a/shared/inotify/doc/html/classInotifyEvent__coll__graph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.map b/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.map deleted file mode 100644 index 1d81e141..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotifyEvent.html#3e5d18ff8dea01d14286e4b44a2b76ea" title="Fills the string with all types contained in the event mask." alt="" coords="220,5,383,32"> diff --git a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.md5 b/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.md5 deleted file mode 100644 index 2875d2e2..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -ebd2a62891a75f2964da29826a4d947b
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.png b/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.png Binary files differdeleted file mode 100644 index 85b50381..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c08a0a26ea33dbe94aaf1ac830c103a5_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.map b/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.map deleted file mode 100644 index 15b19bcc..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="204,5,351,32"> diff --git a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.md5 b/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.md5 deleted file mode 100644 index 97058b10..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -c6ebbbab9c151deb92ff69c8b2dd93a1
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.png b/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.png Binary files differdeleted file mode 100644 index 6ede661d..00000000 --- a/shared/inotify/doc/html/classInotifyEvent_c7160544f6f4f24611df57a4422ac47f_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyException-members.html b/shared/inotify/doc/html/classInotifyException-members.html deleted file mode 100644 index 27079a8a..00000000 --- a/shared/inotify/doc/html/classInotifyException-members.html +++ /dev/null @@ -1,36 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Member List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyException Member List</h1>This is the complete list of members for <a class="el" href="classInotifyException.html">InotifyException</a>, including all inherited members.<p><table> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d">GetErrorNumber</a>() const </td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#6364ea375697356805d47cff957dd757">GetMessage</a>() const </td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408">GetSource</a>() const </td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb">InotifyException</a>(const std::string &rMsg="", int iErr=0, void *pSrc=NULL)</td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">m_err</a></td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [protected]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">m_msg</a></td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [protected]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">m_pSrc</a></td><td><a class="el" href="classInotifyException.html">InotifyException</a></td><td><code> [mutable, protected]</code></td></tr> -</table></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyException.html b/shared/inotify/doc/html/classInotifyException.html deleted file mode 100644 index 6b3b55bf..00000000 --- a/shared/inotify/doc/html/classInotifyException.html +++ /dev/null @@ -1,232 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: InotifyException Class Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyException Class Reference</h1><!-- doxytag: class="InotifyException" -->Class for inotify exceptions. -<a href="#_details">More...</a> -<p> -<code>#include <<a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a>></code> -<p> - -<p> -<a href="classInotifyException-members.html">List of all members.</a><table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb">InotifyException</a> (const std::string &rMsg="", int iErr=0, void *pSrc=NULL)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Constructor. <a href="#900dc29e5cfb3ece6c1651d04773b2bb"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">const std::string & </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#6364ea375697356805d47cff957dd757">GetMessage</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the exception message. <a href="#6364ea375697356805d47cff957dd757"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d">GetErrorNumber</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the exception error number. <a href="#60d885f998a6cb97d06111e6aded155d"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408">GetSource</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the exception source. <a href="#619e8b963faebdefb283d79b5ae5c408"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Protected Attributes</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">std::string </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">m_msg</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">message <a href="#c113719bd6f4352e12876b2322f1c92c"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">m_err</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">error number <a href="#aa8a163c661ce70e34b3e3e7ad700854"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">m_pSrc</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">source <a href="#dd106c2255890025561245cf91fe1427"></a><br></td></tr> -</table> -<hr><a name="_details"></a><h2>Detailed Description</h2> -Class for inotify exceptions. -<p> -This class allows to acquire information about exceptional events. It makes easier to log or display error messages and to identify problematic code locations.<p> -Although this class is basically thread-safe it is not intended to be shared between threads. <hr><h2>Constructor & Destructor Documentation</h2> -<a class="anchor" name="900dc29e5cfb3ece6c1651d04773b2bb"></a><!-- doxytag: member="InotifyException::InotifyException" ref="900dc29e5cfb3ece6c1651d04773b2bb" args="(const std::string &rMsg="", int iErr=0, void *pSrc=NULL)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyException::InotifyException </td> - <td>(</td> - <td class="paramtype">const std::string & </td> - <td class="paramname"> <em>rMsg</em> = <code>""</code>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">int </td> - <td class="paramname"> <em>iErr</em> = <code>0</code>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">void * </td> - <td class="paramname"> <em>pSrc</em> = <code>NULL</code></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Constructor. -<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rMsg</em> </td><td>message </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>iErr</em> </td><td>error number (see errno.h) </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>pSrc</em> </td><td>source </td></tr> - </table> -</dl> - -</div> -</div><p> -<hr><h2>Member Function Documentation</h2> -<a class="anchor" name="60d885f998a6cb97d06111e6aded155d"></a><!-- doxytag: member="InotifyException::GetErrorNumber" ref="60d885f998a6cb97d06111e6aded155d" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int InotifyException::GetErrorNumber </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the exception error number. -<p> -If not applicable this value is 0 (zero).<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>error number (standardized; see errno.h) </dd></dl> - -</div> -</div><p> -<a class="anchor" name="6364ea375697356805d47cff957dd757"></a><!-- doxytag: member="InotifyException::GetMessage" ref="6364ea375697356805d47cff957dd757" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">const std::string& InotifyException::GetMessage </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the exception message. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>message </dd></dl> - -</div> -</div><p> -<a class="anchor" name="619e8b963faebdefb283d79b5ae5c408"></a><!-- doxytag: member="InotifyException::GetSource" ref="619e8b963faebdefb283d79b5ae5c408" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void* InotifyException::GetSource </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the exception source. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>source </dd></dl> - -</div> -</div><p> -<hr><h2>Member Data Documentation</h2> -<a class="anchor" name="aa8a163c661ce70e34b3e3e7ad700854"></a><!-- doxytag: member="InotifyException::m_err" ref="aa8a163c661ce70e34b3e3e7ad700854" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int <a class="el" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">InotifyException::m_err</a><code> [protected]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -error number -<p> - -</div> -</div><p> -<a class="anchor" name="c113719bd6f4352e12876b2322f1c92c"></a><!-- doxytag: member="InotifyException::m_msg" ref="c113719bd6f4352e12876b2322f1c92c" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">std::string <a class="el" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">InotifyException::m_msg</a><code> [protected]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -message -<p> - -</div> -</div><p> -<a class="anchor" name="dd106c2255890025561245cf91fe1427"></a><!-- doxytag: member="InotifyException::m_pSrc" ref="dd106c2255890025561245cf91fe1427" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void* <a class="el" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">InotifyException::m_pSrc</a><code> [mutable, protected]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -source -<p> - -</div> -</div><p> -<hr>The documentation for this class was generated from the following file:<ul> -<li><a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a></ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyWatch-members.html b/shared/inotify/doc/html/classInotifyWatch-members.html deleted file mode 100644 index 00668fc3..00000000 --- a/shared/inotify/doc/html/classInotifyWatch-members.html +++ /dev/null @@ -1,46 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Member List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyWatch Member List</h1>This is the complete list of members for <a class="el" href="classInotifyWatch.html">InotifyWatch</a>, including all inherited members.<p><table> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#804cdc1e9579a075a60c239b202559f4">__Disable</a>()</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59">GetDescriptor</a>() const </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0">GetInotify</a>()</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009">GetMask</a>() const </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2">GetPath</a>() const </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#94bfb861dc18ca5d16abfcff90db8c86">Inotify</a> class</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [friend]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9">InotifyWatch</a>(const std::string &rPath, int32_t uMask, bool fEnabled=true)</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324">IsEnabled</a>() const </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55">IsRecursive</a>() const </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">m_fEnabled</a></td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">m_path</a></td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">m_pInotify</a></td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">m_uMask</a></td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">m_wd</a></td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [private]</code></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#a71aff8650fadff32a3c655ca50945f1">SetEnabled</a>(bool fEnabled)</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#3ad7fbc55c21b3fcd08c2d1d388e14b6">SetMask</a>(uint32_t uMask)</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td></td></tr> - <tr class="memlist"><td><a class="el" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef">~InotifyWatch</a>()</td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td><td><code> [inline]</code></td></tr> -</table></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyWatch.html b/shared/inotify/doc/html/classInotifyWatch.html deleted file mode 100644 index bc4f53e9..00000000 --- a/shared/inotify/doc/html/classInotifyWatch.html +++ /dev/null @@ -1,533 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: InotifyWatch Class Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>InotifyWatch Class Reference</h1><!-- doxytag: class="InotifyWatch" -->inotify watch class -<a href="#_details">More...</a> -<p> -<code>#include <<a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a>></code> -<p> -<div class="dynheader"> -Collaboration diagram for InotifyWatch:</div> -<div class="dynsection"> -<p><center><img src="classInotifyWatch__coll__graph.png" border="0" usemap="#InotifyWatch__coll__map" alt="Collaboration graph"></center> -<map name="InotifyWatch__coll__map"> -<area shape="rect" href="classInotify.html" title="inotify class" alt="" coords="24,5,80,32"></map> -<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center></div> - -<p> -<a href="classInotifyWatch-members.html">List of all members.</a><table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9">InotifyWatch</a> (const std::string &rPath, int32_t uMask, bool fEnabled=true)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Constructor. <a href="#c9c02f1dbd143eebd711eba03ac366e9"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef">~InotifyWatch</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Destructor. <a href="#871c16b01aa8841b36246e5b629ecaef"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59">GetDescriptor</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the watch descriptor. <a href="#855f982421402dd63d064dde328f2a59"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">const std::string & </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2">GetPath</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the watched file path. <a href="#2e659c699e7d43bd0a218fe4905784d2"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009">GetMask</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the watch event mask. <a href="#f759f9baca6f4abbbaae57e076486009"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#3ad7fbc55c21b3fcd08c2d1d388e14b6">SetMask</a> (uint32_t uMask) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Sets the watch event mask. <a href="#3ad7fbc55c21b3fcd08c2d1d388e14b6"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotify.html">Inotify</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0">GetInotify</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Returns the appropriate inotify class instance. <a href="#cbf0042d06841f9503405b104e4c35d0"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#a71aff8650fadff32a3c655ca50945f1">SetEnabled</a> (bool fEnabled) throw (InotifyException)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Enables/disables the watch. <a href="#a71aff8650fadff32a3c655ca50945f1"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324">IsEnabled</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Checks whether the watch is enabled. <a href="#5ab551a912e5acff6a9c74baaf9ea324"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55">IsRecursive</a> () const </td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Checks whether the watch is recursive. <a href="#222c911ef0e8d6f61570489ed6042e55"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Private Member Functions</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">IN_LOCK_DECL void </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#804cdc1e9579a075a60c239b202559f4">__Disable</a> ()</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Disables the watch (due to removing by the kernel). <a href="#804cdc1e9579a075a60c239b202559f4"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Private Attributes</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">std::string </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">m_path</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">watched file path <a href="#a63ba30ffdb8b9db27970bb1099e4db5"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">m_uMask</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">event mask <a href="#f725ea61e3252adae6153ecb80de23a8"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">m_wd</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">watch descriptor <a href="#90a78898dc850b238e713e0db284fb0a"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="el" href="classInotify.html">Inotify</a> * </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">m_pInotify</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify object <a href="#ea695aa11f6105184df1ef265be3f1b9"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">m_fEnabled</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">events enabled yes/no <a href="#b0c23c89cc2996bdf6f41b8ef1f1ed18"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Friends</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html#94bfb861dc18ca5d16abfcff90db8c86">Inotify</a></td></tr> - -</table> -<hr><a name="_details"></a><h2>Detailed Description</h2> -inotify watch class -<p> -It holds information about the inotify watch on a particular inode.<p> -If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. <hr><h2>Constructor & Destructor Documentation</h2> -<a class="anchor" name="c9c02f1dbd143eebd711eba03ac366e9"></a><!-- doxytag: member="InotifyWatch::InotifyWatch" ref="c9c02f1dbd143eebd711eba03ac366e9" args="(const std::string &rPath, int32_t uMask, bool fEnabled=true)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyWatch::InotifyWatch </td> - <td>(</td> - <td class="paramtype">const std::string & </td> - <td class="paramname"> <em>rPath</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">int32_t </td> - <td class="paramname"> <em>uMask</em>, </td> - </tr> - <tr> - <td class="paramkey"></td> - <td></td> - <td class="paramtype">bool </td> - <td class="paramname"> <em>fEnabled</em> = <code>true</code></td><td> </td> - </tr> - <tr> - <td></td> - <td>)</td> - <td></td><td></td><td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Constructor. -<p> -Creates an inotify watch. Because this watch is inactive it has an invalid descriptor (-1).<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>rPath</em> </td><td>watched file path </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uMask</em> </td><td>mask for events </td></tr> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>fEnabled</em> </td><td>events enabled yes/no </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="871c16b01aa8841b36246e5b629ecaef"></a><!-- doxytag: member="InotifyWatch::~InotifyWatch" ref="871c16b01aa8841b36246e5b629ecaef" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">InotifyWatch::~InotifyWatch </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Destructor. -<p> - -</div> -</div><p> -<hr><h2>Member Function Documentation</h2> -<a class="anchor" name="804cdc1e9579a075a60c239b202559f4"></a><!-- doxytag: member="InotifyWatch::__Disable" ref="804cdc1e9579a075a60c239b202559f4" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyWatch::__Disable </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [private]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Disables the watch (due to removing by the kernel). -<p> -This method must be called after receiving an event. It ensures the watch object is consistent with the kernel data. -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.png" border="0" usemap="#classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph_map" alt=""></center> -<map name="classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph_map"> -<area shape="rect" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="215,5,361,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="855f982421402dd63d064dde328f2a59"></a><!-- doxytag: member="InotifyWatch::GetDescriptor" ref="855f982421402dd63d064dde328f2a59" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int32_t InotifyWatch::GetDescriptor </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the watch descriptor. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>watch descriptor; -1 for inactive watch </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.png" border="0" usemap="#classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph_map" alt=""></center> -<map name="classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph_map"> -<area shape="rect" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341" title="Returns the event watch descriptor." alt="" coords="235,5,411,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="cbf0042d06841f9503405b104e4c35d0"></a><!-- doxytag: member="InotifyWatch::GetInotify" ref="cbf0042d06841f9503405b104e4c35d0" args="()" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotify.html">Inotify</a>* InotifyWatch::GetInotify </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td><code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the appropriate inotify class instance. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>inotify instance </dd></dl> - -</div> -</div><p> -<a class="anchor" name="f759f9baca6f4abbbaae57e076486009"></a><!-- doxytag: member="InotifyWatch::GetMask" ref="f759f9baca6f4abbbaae57e076486009" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t InotifyWatch::GetMask </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the watch event mask. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>event mask </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.png" border="0" usemap="#classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph_map" alt=""></center> -<map name="classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph_map"> -<area shape="rect" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch." alt="" coords="240,5,325,32"><area shape="rect" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="209,56,356,83"><area shape="rect" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="407,5,492,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="2e659c699e7d43bd0a218fe4905784d2"></a><!-- doxytag: member="InotifyWatch::GetPath" ref="2e659c699e7d43bd0a218fe4905784d2" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">const std::string& InotifyWatch::GetPath </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Returns the watched file path. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>file path </dd></dl> - -<p> -<div class="dynheader"> -Here is the caller graph for this function:</div> -<div class="dynsection"> -<p><center><img src="classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.png" border="0" usemap="#classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph_map" alt=""></center> -<map name="classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph_map"> -<area shape="rect" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch." alt="" coords="204,5,289,32"><area shape="rect" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="340,5,425,32"></map> -</div> - -</div> -</div><p> -<a class="anchor" name="5ab551a912e5acff6a9c74baaf9ea324"></a><!-- doxytag: member="InotifyWatch::IsEnabled" ref="5ab551a912e5acff6a9c74baaf9ea324" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool InotifyWatch::IsEnabled </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Checks whether the watch is enabled. -<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>true = enables, false = disabled </dd></dl> - -</div> -</div><p> -<a class="anchor" name="222c911ef0e8d6f61570489ed6042e55"></a><!-- doxytag: member="InotifyWatch::IsRecursive" ref="222c911ef0e8d6f61570489ed6042e55" args="() const " --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool InotifyWatch::IsRecursive </td> - <td>(</td> - <td class="paramname"> </td> - <td> ) </td> - <td> const<code> [inline]</code></td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Checks whether the watch is recursive. -<p> -A recursive watch monitors a directory itself and all its subdirectories. This watch is a logical object which may have many underlying kernel watches.<p> -<dl class="return" compact><dt><b>Returns:</b></dt><dd>currently always false (recursive watches not yet supported) </dd></dl> -<dl class="attention" compact><dt><b>Attention:</b></dt><dd>Recursive watches are currently NOT supported. They are planned for future versions. </dd></dl> - -</div> -</div><p> -<a class="anchor" name="a71aff8650fadff32a3c655ca50945f1"></a><!-- doxytag: member="InotifyWatch::SetEnabled" ref="a71aff8650fadff32a3c655ca50945f1" args="(bool fEnabled)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyWatch::SetEnabled </td> - <td>(</td> - <td class="paramtype">bool </td> - <td class="paramname"> <em>fEnabled</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Enables/disables the watch. -<p> -If the watch is active (added to an instance of <a class="el" href="classInotify.html" title="inotify class">Inotify</a>) this method may fail due to unsuccessful re-setting the watch in the kernel.<p> -Re-setting the current state has no effect.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>fEnabled</em> </td><td>set enabled yes/no</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if enabling/disabling fails </td></tr> - </table> -</dl> - -</div> -</div><p> -<a class="anchor" name="3ad7fbc55c21b3fcd08c2d1d388e14b6"></a><!-- doxytag: member="InotifyWatch::SetMask" ref="3ad7fbc55c21b3fcd08c2d1d388e14b6" args="(uint32_t uMask)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">void InotifyWatch::SetMask </td> - <td>(</td> - <td class="paramtype">uint32_t </td> - <td class="paramname"> <em>uMask</em> </td> - <td> ) </td> - <td> throw (<a class="el" href="classInotifyException.html">InotifyException</a>)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Sets the watch event mask. -<p> -If the watch is active (added to an instance of <a class="el" href="classInotify.html" title="inotify class">Inotify</a>) this method may fail due to unsuccessful re-setting the watch in the kernel.<p> -<dl compact><dt><b>Parameters:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"><tt>[in]</tt> </td><td valign="top"><em>uMask</em> </td><td>event mask</td></tr> - </table> -</dl> -<dl compact><dt><b>Exceptions:</b></dt><dd> - <table border="0" cellspacing="2" cellpadding="0"> - <tr><td valign="top"></td><td valign="top"><em><a class="el" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a></em> </td><td>thrown if changing fails </td></tr> - </table> -</dl> - -</div> -</div><p> -<hr><h2>Friends And Related Function Documentation</h2> -<a class="anchor" name="94bfb861dc18ca5d16abfcff90db8c86"></a><!-- doxytag: member="InotifyWatch::Inotify" ref="94bfb861dc18ca5d16abfcff90db8c86" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">friend class <a class="el" href="classInotify.html">Inotify</a><code> [friend]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<hr><h2>Member Data Documentation</h2> -<a class="anchor" name="b0c23c89cc2996bdf6f41b8ef1f1ed18"></a><!-- doxytag: member="InotifyWatch::m_fEnabled" ref="b0c23c89cc2996bdf6f41b8ef1f1ed18" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">bool <a class="el" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">InotifyWatch::m_fEnabled</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -events enabled yes/no -<p> - -</div> -</div><p> -<a class="anchor" name="a63ba30ffdb8b9db27970bb1099e4db5"></a><!-- doxytag: member="InotifyWatch::m_path" ref="a63ba30ffdb8b9db27970bb1099e4db5" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">std::string <a class="el" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">InotifyWatch::m_path</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -watched file path -<p> - -</div> -</div><p> -<a class="anchor" name="ea695aa11f6105184df1ef265be3f1b9"></a><!-- doxytag: member="InotifyWatch::m_pInotify" ref="ea695aa11f6105184df1ef265be3f1b9" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname"><a class="el" href="classInotify.html">Inotify</a>* <a class="el" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">InotifyWatch::m_pInotify</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -inotify object -<p> - -</div> -</div><p> -<a class="anchor" name="f725ea61e3252adae6153ecb80de23a8"></a><!-- doxytag: member="InotifyWatch::m_uMask" ref="f725ea61e3252adae6153ecb80de23a8" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">uint32_t <a class="el" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">InotifyWatch::m_uMask</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -event mask -<p> - -</div> -</div><p> -<a class="anchor" name="90a78898dc850b238e713e0db284fb0a"></a><!-- doxytag: member="InotifyWatch::m_wd" ref="90a78898dc850b238e713e0db284fb0a" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">int32_t <a class="el" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">InotifyWatch::m_wd</a><code> [private]</code> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -watch descriptor -<p> - -</div> -</div><p> -<hr>The documentation for this class was generated from the following files:<ul> -<li><a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a><li><a class="el" href="inotify-cxx_8cpp.html">inotify-cxx.cpp</a></ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.map b/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.map deleted file mode 100644 index f27ca8a7..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.map +++ /dev/null @@ -1,2 +0,0 @@ -<area shape="rect" href="$classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch." alt="" coords="204,5,289,32"> -<area shape="rect" href="$classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="340,5,425,32"> diff --git a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.md5 b/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.md5 deleted file mode 100644 index fbd2ff03..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -620e1e417c7b3a584d9a02e4d00e9a65
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.png b/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.png Binary files differdeleted file mode 100644 index a8cfc58a..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_2e659c699e7d43bd0a218fe4905784d2_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.map b/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.map deleted file mode 100644 index 45f1c8f4..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="215,5,361,32"> diff --git a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.md5 b/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.md5 deleted file mode 100644 index f49498f5..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -74fca07ef5cdde676f9befabdba3c390
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.png b/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.png Binary files differdeleted file mode 100644 index 9adcc985..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_804cdc1e9579a075a60c239b202559f4_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.map b/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.map deleted file mode 100644 index dff1f4a3..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341" title="Returns the event watch descriptor." alt="" coords="235,5,411,32"> diff --git a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.md5 b/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.md5 deleted file mode 100644 index 17145c3b..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -9338607b3d3a0e2804e6ced197d5c9cc
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.png b/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.png Binary files differdeleted file mode 100644 index 5e7dd132..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_855f982421402dd63d064dde328f2a59_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyWatch__coll__graph.map b/shared/inotify/doc/html/classInotifyWatch__coll__graph.map deleted file mode 100644 index 59ebb091..00000000 --- a/shared/inotify/doc/html/classInotifyWatch__coll__graph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html" title="inotify class" alt="" coords="24,5,80,32"> diff --git a/shared/inotify/doc/html/classInotifyWatch__coll__graph.md5 b/shared/inotify/doc/html/classInotifyWatch__coll__graph.md5 deleted file mode 100644 index f8ab3a5e..00000000 --- a/shared/inotify/doc/html/classInotifyWatch__coll__graph.md5 +++ /dev/null @@ -1 +0,0 @@ -4b0e82ffc859966b60e2fb5b19162d43
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyWatch__coll__graph.png b/shared/inotify/doc/html/classInotifyWatch__coll__graph.png Binary files differdeleted file mode 100644 index b2a5567f..00000000 --- a/shared/inotify/doc/html/classInotifyWatch__coll__graph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.map b/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.map deleted file mode 100644 index ae5eb580..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.map +++ /dev/null @@ -1,3 +0,0 @@ -<area shape="rect" href="$classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch." alt="" coords="240,5,325,32"> -<area shape="rect" href="$classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events." alt="" coords="209,56,356,83"> -<area shape="rect" href="$classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="407,5,492,32"> diff --git a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.md5 b/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.md5 deleted file mode 100644 index 30d2f7a4..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -126051def76cebe39a5ea1e3b30484e7
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.png b/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.png Binary files differdeleted file mode 100644 index 104b6dbb..00000000 --- a/shared/inotify/doc/html/classInotifyWatch_f759f9baca6f4abbbaae57e076486009_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.map b/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.map deleted file mode 100644 index c916a719..00000000 --- a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#287dc0d238fa6edc3269441cb284f979" title="Extracts a queued inotify event (without removing)." alt="" coords="179,5,304,32"> diff --git a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.md5 b/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.md5 deleted file mode 100644 index 4dc02268..00000000 --- a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -867a37f8a90b3c381b26aff122c509e1
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.png b/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.png Binary files differdeleted file mode 100644 index 368ea909..00000000 --- a/shared/inotify/doc/html/classInotify_19cde43d082ff92bd02654610019300d_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.map b/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.map deleted file mode 100644 index ee280ed5..00000000 --- a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#ac1a52b2ff6bfec07021a44e55d496a6" title="Removes a watch." alt="" coords="163,5,272,32"> diff --git a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.md5 b/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.md5 deleted file mode 100644 index 631afbc4..00000000 --- a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -587f8ec5057bea5f3b570a712828014d
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.png b/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.png Binary files differdeleted file mode 100644 index 0c72efe9..00000000 --- a/shared/inotify/doc/html/classInotify_21c39bb8e5bbc1941b945c18f9005b84_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.map b/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.map deleted file mode 100644 index 57880c92..00000000 --- a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#35dab56d3e10bf28b5e457871adddb58" title="Adds a new watch." alt="" coords="143,5,228,32"> diff --git a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.md5 b/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.md5 deleted file mode 100644 index 44962c4b..00000000 --- a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -8d7a6b2b3b84fb672bc0326258ff14f6
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.png b/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.png Binary files differdeleted file mode 100644 index 65078cda..00000000 --- a/shared/inotify/doc/html/classInotify_2ef771ebaf982d76ebe19b3f5bc9cd83_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.map b/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.map deleted file mode 100644 index dc7351fd..00000000 --- a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#b028c8fa988f6bbb2ef773db3ea3a2d3" title="Extracts a queued inotify event." alt="" coords="172,5,287,32"> diff --git a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.md5 b/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.md5 deleted file mode 100644 index 2cdfd2b4..00000000 --- a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -04c6a964e2bb5f8eaec7dbb9c83b2bc7
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.png b/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.png Binary files differdeleted file mode 100644 index fd43491a..00000000 --- a/shared/inotify/doc/html/classInotify_490a3f824c6d041d31ccaabe9bd92008_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.map b/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.map deleted file mode 100644 index 30031126..00000000 --- a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.map +++ /dev/null @@ -1,3 +0,0 @@ -<area shape="rect" href="$classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42" title="Returns the maximum number of events in the kernel queue." alt="" coords="204,5,351,32"> -<area shape="rect" href="$classInotify.html#c18b7732f67832260fbbd47aebb8af51" title="Returns the maximum number of inotify instances per process." alt="" coords="195,56,360,83"> -<area shape="rect" href="$classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f" title="Returns the maximum number of inotify watches per instance." alt="" coords="197,107,357,133"> diff --git a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.md5 b/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.md5 deleted file mode 100644 index cf32572b..00000000 --- a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -d00e8e6b410a8b99056c20c2ae513bab
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.png b/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.png Binary files differdeleted file mode 100644 index 5102409d..00000000 --- a/shared/inotify/doc/html/classInotify_70b3b57e8661fbb4c5bc404b86225c3b_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.map b/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.map deleted file mode 100644 index 37e43de7..00000000 --- a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.map +++ /dev/null @@ -1,3 +0,0 @@ -<area shape="rect" href="$classInotify.html#66d90ebfa516d4bd1463749def2b58f9" title="Sets the maximum number of events in the kernel queue." alt="" coords="204,5,351,32"> -<area shape="rect" href="$classInotify.html#620c891962fe5acd26485c64e9b28d19" title="Sets the maximum number of inotify instances per process." alt="" coords="196,56,359,83"> -<area shape="rect" href="$classInotify.html#5064380cdb4a726ab33f3fa18d15c77a" title="Sets the maximum number of inotify watches per instance." alt="" coords="197,107,357,133"> diff --git a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.md5 b/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.md5 deleted file mode 100644 index 9017da9c..00000000 --- a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -1d28be277b69710e355fb579217e5b78
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.png b/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.png Binary files differdeleted file mode 100644 index a58ed2be..00000000 --- a/shared/inotify/doc/html/classInotify_734538233ba2136164f76f4df6c3654e_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.map b/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.map deleted file mode 100644 index 9ddf26fa..00000000 --- a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$classInotify.html#f19dd5e491395673e4798eb9dbf5f682" title="Destructor." alt="" coords="151,5,255,32"> diff --git a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.md5 b/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.md5 deleted file mode 100644 index 5cb8482f..00000000 --- a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -2ac402c3a1e1f917bb08f0f7203eb443
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.png b/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.png Binary files differdeleted file mode 100644 index 83f1c6d4..00000000 --- a/shared/inotify/doc/html/classInotify_86ae86c43ea1a72f562ca46393309635_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.map b/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.map deleted file mode 100644 index 0ab98b58..00000000 --- a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.map +++ /dev/null @@ -1,2 +0,0 @@ -<area shape="rect" href="$classInotify.html#86ae86c43ea1a72f562ca46393309635" title="Removes all watches and closes the inotify device." alt="" coords="179,5,275,32"> -<area shape="rect" href="$classInotify.html#f19dd5e491395673e4798eb9dbf5f682" title="Destructor." alt="" coords="324,5,428,32"> diff --git a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.md5 b/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.md5 deleted file mode 100644 index ca0e1018..00000000 --- a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.md5 +++ /dev/null @@ -1 +0,0 @@ -d6ad52008b7d418d0c5f4e495df76a6f
\ No newline at end of file diff --git a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.png b/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.png Binary files differdeleted file mode 100644 index edba755d..00000000 --- a/shared/inotify/doc/html/classInotify_bc1fd5830ca561efb69bcd2283981741_icgraph.png +++ /dev/null diff --git a/shared/inotify/doc/html/classes.html b/shared/inotify/doc/html/classes.html deleted file mode 100644 index 604cbade..00000000 --- a/shared/inotify/doc/html/classes.html +++ /dev/null @@ -1,32 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Alphabetical List</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>Class Index</h1><p><div class="qindex"><a class="qindex" href="#letter_I">I</a></div><p> -<table align="center" width="95%" border="0" cellspacing="0" cellpadding="0"> -<tr><td><a name="letter_I"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah"> I </div></td></tr></table> -</td><td><a class="el" href="classInotify.html">Inotify</a> </td><td><a class="el" href="classInotifyEvent.html">InotifyEvent</a> </td><td><a class="el" href="classInotifyException.html">InotifyException</a> </td><td><a class="el" href="classInotifyWatch.html">InotifyWatch</a> </td></tr></table><p><div class="qindex"><a class="qindex" href="#letter_I">I</a></div><p> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/doxygen.css b/shared/inotify/doc/html/doxygen.css deleted file mode 100644 index 3767dc95..00000000 --- a/shared/inotify/doc/html/doxygen.css +++ /dev/null @@ -1,441 +0,0 @@ -body, table, div, p, dl { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; -} - -/* @group Heading Levels */ - -h1 { - text-align: center; - font-size: 150%; -} - -h2 { - font-size: 120%; -} - -h3 { - font-size: 100%; -} - -/* @end */ - -caption { - font-weight: bold; -} - -div.qindex, div.navtab{ - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #153788; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #1b77c5; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #6666cc; - color: #ffffff; - border: 1px double #9295C2; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code { -} - -a.codeRef { -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -.fragment { - font-family: monospace, fixed; - font-size: 105%; -} - -pre.fragment { - border: 1px solid #CCCCCC; - background-color: #f5f5f5; - padding: 4px 6px; - margin: 4px 8px 4px 2px; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - margin-bottom: 6px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background: white; - color: black; - margin-right: 20px; - margin-left: 20px; -} - -td.indexkey { - background-color: #e8eef2; - font-weight: bold; - border: 1px solid #CCCCCC; - margin: 2px 0px 2px 0; - padding: 2px 10px; -} - -td.indexvalue { - background-color: #e8eef2; - border: 1px solid #CCCCCC; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #f0f0f0; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -/* @end */ - -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #84b0c7; -} - -th.dirtab { - background: #e8eef2; - font-weight: bold; -} - -hr { - height: 0; - border: none; - border-top: 1px solid #666; -} - -/* @group Member Descriptions */ - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #FAFAFA; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #ccc; -} - -.memTemplParams { - color: #606060; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #606060; - font-weight: normal; - margin-left: 3px; -} - -.memnav { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.memitem { - padding: 0; -} - -.memname { - white-space: nowrap; - font-weight: bold; -} - -.memproto, .memdoc { - border: 1px solid #84b0c7; -} - -.memproto { - padding: 0; - background-color: #d5e1e8; - font-weight: bold; - -webkit-border-top-left-radius: 8px; - -webkit-border-top-right-radius: 8px; - -moz-border-radius-topleft: 8px; - -moz-border-radius-topright: 8px; -} - -.memdoc { - padding: 2px 5px; - background-color: #eef3f5; - border-top-width: 0; - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} - -/* @end */ - -/* @group Directory (tree) */ - -/* for the tree view */ - -.ftvtree { - font-family: sans-serif; - margin: 0.5em; -} - -/* these are for tree view when used as main index */ - -.directory { - font-size: 9pt; - font-weight: bold; -} - -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -/* -The following two styles can be used to replace the root node title -with an image of your choice. Simply uncomment the next two styles, -specify the name of your image and be sure to set 'height' to the -proper pixel height of your image. -*/ - -/* -.directory h3.swap { - height: 61px; - background-repeat: no-repeat; - background-image: url("yourimage.gif"); -} -.directory h3.swap span { - display: none; -} -*/ - -.directory > h3 { - margin-top: 0; -} - -.directory p { - margin: 0px; - white-space: nowrap; -} - -.directory div { - display: none; - margin: 0px; -} - -.directory img { - vertical-align: -30%; -} - -/* these are for tree view when not used as main index */ - -.directory-alt { - font-size: 100%; - font-weight: bold; -} - -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -.directory-alt > h3 { - margin-top: 0; -} - -.directory-alt p { - margin: 0px; - white-space: nowrap; -} - -.directory-alt div { - display: none; - margin: 0px; -} - -.directory-alt img { - vertical-align: -30%; -} - -/* @end */ - -address { - font-style: normal; - color: #333; -} diff --git a/shared/inotify/doc/html/doxygen.png b/shared/inotify/doc/html/doxygen.png Binary files differdeleted file mode 100644 index f0a274bb..00000000 --- a/shared/inotify/doc/html/doxygen.png +++ /dev/null diff --git a/shared/inotify/doc/html/files.html b/shared/inotify/doc/html/files.html deleted file mode 100644 index 5c6b0baf..00000000 --- a/shared/inotify/doc/html/files.html +++ /dev/null @@ -1,32 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: File Index</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li class="current"><a href="files.html"><span>File List</span></a></li> - <li><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>File List</h1>Here is a list of all files with brief descriptions:<table> - <tr><td class="indexkey"><a class="el" href="inotify-cxx_8cpp.html">inotify-cxx.cpp</a></td><td class="indexvalue"><a class="el" href="classInotify.html" title="inotify class">Inotify</a> C++ interface implementation </td></tr> - <tr><td class="indexkey"><a class="el" href="inotify-cxx_8h.html">inotify-cxx.h</a> <a href="inotify-cxx_8h_source.html">[code]</a></td><td class="indexvalue"><a class="el" href="classInotify.html" title="inotify class">Inotify</a> C++ interface header </td></tr> -</table> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/functions.html b/shared/inotify/doc/html/functions.html deleted file mode 100644 index 00a99ed4..00000000 --- a/shared/inotify/doc/html/functions.html +++ /dev/null @@ -1,215 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li class="current"><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li class="current"><a href="functions.html"><span>All</span></a></li> - <li><a href="functions_func.html"><span>Functions</span></a></li> - <li><a href="functions_vars.html"><span>Variables</span></a></li> - <li><a href="functions_rela.html"><span>Related Functions</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="#index__"><span>_</span></a></li> - <li><a href="#index_a"><span>a</span></a></li> - <li><a href="#index_c"><span>c</span></a></li> - <li><a href="#index_d"><span>d</span></a></li> - <li><a href="#index_f"><span>f</span></a></li> - <li><a href="#index_g"><span>g</span></a></li> - <li><a href="#index_i"><span>i</span></a></li> - <li><a href="#index_m"><span>m</span></a></li> - <li><a href="#index_p"><span>p</span></a></li> - <li><a href="#index_r"><span>r</span></a></li> - <li><a href="#index_s"><span>s</span></a></li> - <li><a href="#index_w"><span>w</span></a></li> - <li><a href="#index_~"><span>~</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -Here is a list of all class members with links to the classes they belong to: -<p> -<h3><a class="anchor" name="index__">- _ -</a></h3><ul> -<li>__Disable() -: <a class="el" href="classInotifyWatch.html#804cdc1e9579a075a60c239b202559f4">InotifyWatch</a> -</ul> -<h3><a class="anchor" name="index_a">- a -</a></h3><ul> -<li>Add() -: <a class="el" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83">Inotify</a> -</ul> -<h3><a class="anchor" name="index_c">- c -</a></h3><ul> -<li>Close() -: <a class="el" href="classInotify.html#86ae86c43ea1a72f562ca46393309635">Inotify</a> -</ul> -<h3><a class="anchor" name="index_d">- d -</a></h3><ul> -<li>DumpTypes() -: <a class="el" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5">InotifyEvent</a> -</ul> -<h3><a class="anchor" name="index_f">- f -</a></h3><ul> -<li>FindWatch() -: <a class="el" href="classInotify.html#182d19b667c9e0899802b70a579eff40">Inotify</a> -</ul> -<h3><a class="anchor" name="index_g">- g -</a></h3><ul> -<li>GetCapability() -: <a class="el" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b">Inotify</a> -<li>GetCapabilityPath() -: <a class="el" href="classInotify.html#0233ddfe40844d729505fdfd709d22cc">Inotify</a> -<li>GetCookie() -: <a class="el" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17">InotifyEvent</a> -<li>GetDescriptor() -: <a class="el" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341">InotifyEvent</a> -, <a class="el" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59">InotifyWatch</a> -, <a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9">Inotify</a> -<li>GetEnabledCount() -: <a class="el" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063">Inotify</a> -<li>GetErrorNumber() -: <a class="el" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d">InotifyException</a> -<li>GetEvent() -: <a class="el" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008">Inotify</a> -<li>GetEventCount() -: <a class="el" href="classInotify.html#a3c533f956871f904949832ac8f5fbde">Inotify</a> -<li>GetInotify() -: <a class="el" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0">InotifyWatch</a> -<li>GetLength() -: <a class="el" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a">InotifyEvent</a> -<li>GetMask() -: <a class="el" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009">InotifyWatch</a> -, <a class="el" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f">InotifyEvent</a> -<li>GetMaskByName() -: <a class="el" href="classInotifyEvent.html#eced3a88a6dea190c5df19c2a6599010">InotifyEvent</a> -<li>GetMaxEvents() -: <a class="el" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42">Inotify</a> -<li>GetMaxInstances() -: <a class="el" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51">Inotify</a> -<li>GetMaxWatches() -: <a class="el" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f">Inotify</a> -<li>GetMessage() -: <a class="el" href="classInotifyException.html#6364ea375697356805d47cff957dd757">InotifyException</a> -<li>GetName() -: <a class="el" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f">InotifyEvent</a> -<li>GetPath() -: <a class="el" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2">InotifyWatch</a> -<li>GetSource() -: <a class="el" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408">InotifyException</a> -<li>GetWatch() -: <a class="el" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92">InotifyEvent</a> -<li>GetWatchCount() -: <a class="el" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075">Inotify</a> -</ul> -<h3><a class="anchor" name="index_i">- i -</a></h3><ul> -<li>Inotify -: <a class="el" href="classInotifyWatch.html#94bfb861dc18ca5d16abfcff90db8c86">InotifyWatch</a> -, <a class="el" href="classInotify.html#a6fe6e9cb3343665eb968fcd5170cfb9">Inotify</a> -<li>InotifyEvent() -: <a class="el" href="classInotifyEvent.html#6d7f3fc0f51580da4a3ec2348609df64">InotifyEvent</a> -<li>InotifyException() -: <a class="el" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb">InotifyException</a> -<li>InotifyWatch() -: <a class="el" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9">InotifyWatch</a> -, <a class="el" href="classInotify.html#10880f490c33acd8bd24664fc7bce4ae">Inotify</a> -<li>IsEnabled() -: <a class="el" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324">InotifyWatch</a> -<li>IsRecursive() -: <a class="el" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55">InotifyWatch</a> -<li>IsType() -: <a class="el" href="classInotifyEvent.html#477ae71116ec393434a1f62a7170a156">InotifyEvent</a> -</ul> -<h3><a class="anchor" name="index_m">- m -</a></h3><ul> -<li>m_buf -: <a class="el" href="classInotify.html#eee7847efd93b681fddac56860fc7958">Inotify</a> -<li>m_err -: <a class="el" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">InotifyException</a> -<li>m_events -: <a class="el" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">Inotify</a> -<li>m_fd -: <a class="el" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">Inotify</a> -<li>m_fEnabled -: <a class="el" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">InotifyWatch</a> -<li>m_msg -: <a class="el" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">InotifyException</a> -<li>m_name -: <a class="el" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">InotifyEvent</a> -<li>m_path -: <a class="el" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">InotifyWatch</a> -<li>m_paths -: <a class="el" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">Inotify</a> -<li>m_pInotify -: <a class="el" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">InotifyWatch</a> -<li>m_pSrc -: <a class="el" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">InotifyException</a> -<li>m_pWatch -: <a class="el" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">InotifyEvent</a> -<li>m_uCookie -: <a class="el" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">InotifyEvent</a> -<li>m_uMask -: <a class="el" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">InotifyWatch</a> -, <a class="el" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">InotifyEvent</a> -<li>m_watches -: <a class="el" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">Inotify</a> -<li>m_wd -: <a class="el" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">InotifyWatch</a> -</ul> -<h3><a class="anchor" name="index_p">- p -</a></h3><ul> -<li>PeekEvent() -: <a class="el" href="classInotify.html#19cde43d082ff92bd02654610019300d">Inotify</a> -</ul> -<h3><a class="anchor" name="index_r">- r -</a></h3><ul> -<li>Remove() -: <a class="el" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84">Inotify</a> -<li>RemoveAll() -: <a class="el" href="classInotify.html#bc1fd5830ca561efb69bcd2283981741">Inotify</a> -</ul> -<h3><a class="anchor" name="index_s">- s -</a></h3><ul> -<li>SetCapability() -: <a class="el" href="classInotify.html#734538233ba2136164f76f4df6c3654e">Inotify</a> -<li>SetCloseOnExec() -: <a class="el" href="classInotify.html#124dd5816205900af61034d47ae65255">Inotify</a> -<li>SetEnabled() -: <a class="el" href="classInotifyWatch.html#a71aff8650fadff32a3c655ca50945f1">InotifyWatch</a> -<li>SetMask() -: <a class="el" href="classInotifyWatch.html#3ad7fbc55c21b3fcd08c2d1d388e14b6">InotifyWatch</a> -<li>SetMaxEvents() -: <a class="el" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9">Inotify</a> -<li>SetMaxInstances() -: <a class="el" href="classInotify.html#620c891962fe5acd26485c64e9b28d19">Inotify</a> -<li>SetMaxWatches() -: <a class="el" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a">Inotify</a> -<li>SetNonBlock() -: <a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b">Inotify</a> -</ul> -<h3><a class="anchor" name="index_w">- w -</a></h3><ul> -<li>WaitForEvents() -: <a class="el" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b">Inotify</a> -</ul> -<h3><a class="anchor" name="index_~">- ~ -</a></h3><ul> -<li>~Inotify() -: <a class="el" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682">Inotify</a> -<li>~InotifyEvent() -: <a class="el" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888">InotifyEvent</a> -<li>~InotifyWatch() -: <a class="el" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef">InotifyWatch</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/functions_func.html b/shared/inotify/doc/html/functions_func.html deleted file mode 100644 index dad8c830..00000000 --- a/shared/inotify/doc/html/functions_func.html +++ /dev/null @@ -1,177 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members - Functions</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li class="current"><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="functions.html"><span>All</span></a></li> - <li class="current"><a href="functions_func.html"><span>Functions</span></a></li> - <li><a href="functions_vars.html"><span>Variables</span></a></li> - <li><a href="functions_rela.html"><span>Related Functions</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="#index__"><span>_</span></a></li> - <li><a href="#index_a"><span>a</span></a></li> - <li><a href="#index_c"><span>c</span></a></li> - <li><a href="#index_d"><span>d</span></a></li> - <li><a href="#index_f"><span>f</span></a></li> - <li><a href="#index_g"><span>g</span></a></li> - <li><a href="#index_i"><span>i</span></a></li> - <li><a href="#index_p"><span>p</span></a></li> - <li><a href="#index_r"><span>r</span></a></li> - <li><a href="#index_s"><span>s</span></a></li> - <li><a href="#index_w"><span>w</span></a></li> - <li><a href="#index_~"><span>~</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<h3><a class="anchor" name="index__">- _ -</a></h3><ul> -<li>__Disable() -: <a class="el" href="classInotifyWatch.html#804cdc1e9579a075a60c239b202559f4">InotifyWatch</a> -</ul> -<h3><a class="anchor" name="index_a">- a -</a></h3><ul> -<li>Add() -: <a class="el" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83">Inotify</a> -</ul> -<h3><a class="anchor" name="index_c">- c -</a></h3><ul> -<li>Close() -: <a class="el" href="classInotify.html#86ae86c43ea1a72f562ca46393309635">Inotify</a> -</ul> -<h3><a class="anchor" name="index_d">- d -</a></h3><ul> -<li>DumpTypes() -: <a class="el" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5">InotifyEvent</a> -</ul> -<h3><a class="anchor" name="index_f">- f -</a></h3><ul> -<li>FindWatch() -: <a class="el" href="classInotify.html#182d19b667c9e0899802b70a579eff40">Inotify</a> -</ul> -<h3><a class="anchor" name="index_g">- g -</a></h3><ul> -<li>GetCapability() -: <a class="el" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b">Inotify</a> -<li>GetCapabilityPath() -: <a class="el" href="classInotify.html#0233ddfe40844d729505fdfd709d22cc">Inotify</a> -<li>GetCookie() -: <a class="el" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17">InotifyEvent</a> -<li>GetDescriptor() -: <a class="el" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341">InotifyEvent</a> -, <a class="el" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59">InotifyWatch</a> -, <a class="el" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9">Inotify</a> -<li>GetEnabledCount() -: <a class="el" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063">Inotify</a> -<li>GetErrorNumber() -: <a class="el" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d">InotifyException</a> -<li>GetEvent() -: <a class="el" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008">Inotify</a> -<li>GetEventCount() -: <a class="el" href="classInotify.html#a3c533f956871f904949832ac8f5fbde">Inotify</a> -<li>GetInotify() -: <a class="el" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0">InotifyWatch</a> -<li>GetLength() -: <a class="el" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a">InotifyEvent</a> -<li>GetMask() -: <a class="el" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009">InotifyWatch</a> -, <a class="el" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f">InotifyEvent</a> -<li>GetMaskByName() -: <a class="el" href="classInotifyEvent.html#eced3a88a6dea190c5df19c2a6599010">InotifyEvent</a> -<li>GetMaxEvents() -: <a class="el" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42">Inotify</a> -<li>GetMaxInstances() -: <a class="el" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51">Inotify</a> -<li>GetMaxWatches() -: <a class="el" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f">Inotify</a> -<li>GetMessage() -: <a class="el" href="classInotifyException.html#6364ea375697356805d47cff957dd757">InotifyException</a> -<li>GetName() -: <a class="el" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f">InotifyEvent</a> -<li>GetPath() -: <a class="el" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2">InotifyWatch</a> -<li>GetSource() -: <a class="el" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408">InotifyException</a> -<li>GetWatch() -: <a class="el" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92">InotifyEvent</a> -<li>GetWatchCount() -: <a class="el" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075">Inotify</a> -</ul> -<h3><a class="anchor" name="index_i">- i -</a></h3><ul> -<li>Inotify() -: <a class="el" href="classInotify.html#a6fe6e9cb3343665eb968fcd5170cfb9">Inotify</a> -<li>InotifyEvent() -: <a class="el" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046">InotifyEvent</a> -<li>InotifyException() -: <a class="el" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb">InotifyException</a> -<li>InotifyWatch() -: <a class="el" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9">InotifyWatch</a> -<li>IsEnabled() -: <a class="el" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324">InotifyWatch</a> -<li>IsRecursive() -: <a class="el" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55">InotifyWatch</a> -<li>IsType() -: <a class="el" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb">InotifyEvent</a> -</ul> -<h3><a class="anchor" name="index_p">- p -</a></h3><ul> -<li>PeekEvent() -: <a class="el" href="classInotify.html#19cde43d082ff92bd02654610019300d">Inotify</a> -</ul> -<h3><a class="anchor" name="index_r">- r -</a></h3><ul> -<li>Remove() -: <a class="el" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84">Inotify</a> -<li>RemoveAll() -: <a class="el" href="classInotify.html#bc1fd5830ca561efb69bcd2283981741">Inotify</a> -</ul> -<h3><a class="anchor" name="index_s">- s -</a></h3><ul> -<li>SetCapability() -: <a class="el" href="classInotify.html#734538233ba2136164f76f4df6c3654e">Inotify</a> -<li>SetCloseOnExec() -: <a class="el" href="classInotify.html#124dd5816205900af61034d47ae65255">Inotify</a> -<li>SetEnabled() -: <a class="el" href="classInotifyWatch.html#a71aff8650fadff32a3c655ca50945f1">InotifyWatch</a> -<li>SetMask() -: <a class="el" href="classInotifyWatch.html#3ad7fbc55c21b3fcd08c2d1d388e14b6">InotifyWatch</a> -<li>SetMaxEvents() -: <a class="el" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9">Inotify</a> -<li>SetMaxInstances() -: <a class="el" href="classInotify.html#620c891962fe5acd26485c64e9b28d19">Inotify</a> -<li>SetMaxWatches() -: <a class="el" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a">Inotify</a> -<li>SetNonBlock() -: <a class="el" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b">Inotify</a> -</ul> -<h3><a class="anchor" name="index_w">- w -</a></h3><ul> -<li>WaitForEvents() -: <a class="el" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b">Inotify</a> -</ul> -<h3><a class="anchor" name="index_~">- ~ -</a></h3><ul> -<li>~Inotify() -: <a class="el" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682">Inotify</a> -<li>~InotifyEvent() -: <a class="el" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888">InotifyEvent</a> -<li>~InotifyWatch() -: <a class="el" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef">InotifyWatch</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/functions_rela.html b/shared/inotify/doc/html/functions_rela.html deleted file mode 100644 index c59a2852..00000000 --- a/shared/inotify/doc/html/functions_rela.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members - Related Functions</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li class="current"><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="functions.html"><span>All</span></a></li> - <li><a href="functions_func.html"><span>Functions</span></a></li> - <li><a href="functions_vars.html"><span>Variables</span></a></li> - <li class="current"><a href="functions_rela.html"><span>Related Functions</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>Inotify -: <a class="el" href="classInotifyWatch.html#94bfb861dc18ca5d16abfcff90db8c86">InotifyWatch</a> -<li>InotifyWatch -: <a class="el" href="classInotify.html#10880f490c33acd8bd24664fc7bce4ae">Inotify</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/functions_vars.html b/shared/inotify/doc/html/functions_vars.html deleted file mode 100644 index c6f76bf7..00000000 --- a/shared/inotify/doc/html/functions_vars.html +++ /dev/null @@ -1,73 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members - Variables</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li class="current"><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="annotated.html"><span>Class List</span></a></li> - <li class="current"><a href="functions.html"><span>Class Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="functions.html"><span>All</span></a></li> - <li><a href="functions_func.html"><span>Functions</span></a></li> - <li class="current"><a href="functions_vars.html"><span>Variables</span></a></li> - <li><a href="functions_rela.html"><span>Related Functions</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>m_buf -: <a class="el" href="classInotify.html#eee7847efd93b681fddac56860fc7958">Inotify</a> -<li>m_err -: <a class="el" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">InotifyException</a> -<li>m_events -: <a class="el" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">Inotify</a> -<li>m_fd -: <a class="el" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">Inotify</a> -<li>m_fEnabled -: <a class="el" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">InotifyWatch</a> -<li>m_msg -: <a class="el" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">InotifyException</a> -<li>m_name -: <a class="el" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">InotifyEvent</a> -<li>m_path -: <a class="el" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">InotifyWatch</a> -<li>m_paths -: <a class="el" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">Inotify</a> -<li>m_pInotify -: <a class="el" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">InotifyWatch</a> -<li>m_pSrc -: <a class="el" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">InotifyException</a> -<li>m_pWatch -: <a class="el" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">InotifyEvent</a> -<li>m_uCookie -: <a class="el" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">InotifyEvent</a> -<li>m_uMask -: <a class="el" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">InotifyWatch</a> -, <a class="el" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">InotifyEvent</a> -<li>m_watches -: <a class="el" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">Inotify</a> -<li>m_wd -: <a class="el" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">InotifyWatch</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/globals.html b/shared/inotify/doc/html/globals.html deleted file mode 100644 index 52989e59..00000000 --- a/shared/inotify/doc/html/globals.html +++ /dev/null @@ -1,81 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li class="current"><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li class="current"><a href="globals.html"><span>All</span></a></li> - <li><a href="globals_type.html"><span>Typedefs</span></a></li> - <li><a href="globals_enum.html"><span>Enumerations</span></a></li> - <li><a href="globals_eval.html"><span>Enumerator</span></a></li> - <li><a href="globals_defs.html"><span>Defines</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -Here is a list of all file members with links to the files they belong to: -<p> -<ul> -<li>DUMP_SEP -: <a class="el" href="inotify-cxx_8cpp.html#6e5d8f74743466e712bbaf3b1de1e93d">inotify-cxx.cpp</a> -<li>IN_EXC_MSG -: <a class="el" href="inotify-cxx_8h.html#fe6b93f7e09db7022f1f9dd102932e12">inotify-cxx.h</a> -<li>IN_LOCK_DECL -: <a class="el" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766">inotify-cxx.h</a> -<li>IN_LOCK_DONE -: <a class="el" href="inotify-cxx_8h.html#08422ec66fb587c1684afbaa575a53dd">inotify-cxx.h</a> -<li>IN_LOCK_INIT -: <a class="el" href="inotify-cxx_8h.html#981aa546075fba39715fd2f63a41f575">inotify-cxx.h</a> -<li>IN_MAX_EVENTS -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1">inotify-cxx.h</a> -<li>IN_MAX_INSTANCES -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9">inotify-cxx.h</a> -<li>IN_MAX_WATCHES -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429">inotify-cxx.h</a> -<li>IN_READ_BEGIN -: <a class="el" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">inotify-cxx.h</a> -<li>IN_READ_END -: <a class="el" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">inotify-cxx.h</a> -<li>IN_READ_END_NOTHROW -: <a class="el" href="inotify-cxx_8h.html#5c6a5be1898ef17662795cc4b420c851">inotify-cxx.h</a> -<li>IN_WATCH_MAP -: <a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">inotify-cxx.h</a> -<li>IN_WP_MAP -: <a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">inotify-cxx.h</a> -<li>IN_WRITE_BEGIN -: <a class="el" href="inotify-cxx_8h.html#c3a6d87ace9403f7ac58f931bbcd9599">inotify-cxx.h</a> -<li>IN_WRITE_END -: <a class="el" href="inotify-cxx_8h.html#f8aeac51b3b4ef56f1791c5c1a2e9cf5">inotify-cxx.h</a> -<li>IN_WRITE_END_NOTHROW -: <a class="el" href="inotify-cxx_8h.html#7e68c4884137939c5e3301f40c198dc7">inotify-cxx.h</a> -<li>INOTIFY_BUFLEN -: <a class="el" href="inotify-cxx_8h.html#a84911f8e42d71161b60d4a28940abb4">inotify-cxx.h</a> -<li>INOTIFY_EVENT_SIZE -: <a class="el" href="inotify-cxx_8h.html#f64b4cc985ba26f31a9cb242153a5014">inotify-cxx.h</a> -<li>InotifyCapability_t -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">inotify-cxx.h</a> -<li>PROCFS_INOTIFY_BASE -: <a class="el" href="inotify-cxx_8cpp.html#481097f28678020b2cbb26dd071a0085">inotify-cxx.cpp</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/globals_defs.html b/shared/inotify/doc/html/globals_defs.html deleted file mode 100644 index 6b434a97..00000000 --- a/shared/inotify/doc/html/globals_defs.html +++ /dev/null @@ -1,69 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li class="current"><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="globals.html"><span>All</span></a></li> - <li><a href="globals_type.html"><span>Typedefs</span></a></li> - <li><a href="globals_enum.html"><span>Enumerations</span></a></li> - <li><a href="globals_eval.html"><span>Enumerator</span></a></li> - <li class="current"><a href="globals_defs.html"><span>Defines</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>DUMP_SEP -: <a class="el" href="inotify-cxx_8cpp.html#6e5d8f74743466e712bbaf3b1de1e93d">inotify-cxx.cpp</a> -<li>IN_EXC_MSG -: <a class="el" href="inotify-cxx_8h.html#fe6b93f7e09db7022f1f9dd102932e12">inotify-cxx.h</a> -<li>IN_LOCK_DECL -: <a class="el" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766">inotify-cxx.h</a> -<li>IN_LOCK_DONE -: <a class="el" href="inotify-cxx_8h.html#08422ec66fb587c1684afbaa575a53dd">inotify-cxx.h</a> -<li>IN_LOCK_INIT -: <a class="el" href="inotify-cxx_8h.html#981aa546075fba39715fd2f63a41f575">inotify-cxx.h</a> -<li>IN_READ_BEGIN -: <a class="el" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">inotify-cxx.h</a> -<li>IN_READ_END -: <a class="el" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">inotify-cxx.h</a> -<li>IN_READ_END_NOTHROW -: <a class="el" href="inotify-cxx_8h.html#5c6a5be1898ef17662795cc4b420c851">inotify-cxx.h</a> -<li>IN_WRITE_BEGIN -: <a class="el" href="inotify-cxx_8h.html#c3a6d87ace9403f7ac58f931bbcd9599">inotify-cxx.h</a> -<li>IN_WRITE_END -: <a class="el" href="inotify-cxx_8h.html#f8aeac51b3b4ef56f1791c5c1a2e9cf5">inotify-cxx.h</a> -<li>IN_WRITE_END_NOTHROW -: <a class="el" href="inotify-cxx_8h.html#7e68c4884137939c5e3301f40c198dc7">inotify-cxx.h</a> -<li>INOTIFY_BUFLEN -: <a class="el" href="inotify-cxx_8h.html#a84911f8e42d71161b60d4a28940abb4">inotify-cxx.h</a> -<li>INOTIFY_EVENT_SIZE -: <a class="el" href="inotify-cxx_8h.html#f64b4cc985ba26f31a9cb242153a5014">inotify-cxx.h</a> -<li>PROCFS_INOTIFY_BASE -: <a class="el" href="inotify-cxx_8cpp.html#481097f28678020b2cbb26dd071a0085">inotify-cxx.cpp</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/globals_enum.html b/shared/inotify/doc/html/globals_enum.html deleted file mode 100644 index 58f68878..00000000 --- a/shared/inotify/doc/html/globals_enum.html +++ /dev/null @@ -1,43 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li class="current"><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="globals.html"><span>All</span></a></li> - <li><a href="globals_type.html"><span>Typedefs</span></a></li> - <li class="current"><a href="globals_enum.html"><span>Enumerations</span></a></li> - <li><a href="globals_eval.html"><span>Enumerator</span></a></li> - <li><a href="globals_defs.html"><span>Defines</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>InotifyCapability_t -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">inotify-cxx.h</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/globals_eval.html b/shared/inotify/doc/html/globals_eval.html deleted file mode 100644 index 53cb2d59..00000000 --- a/shared/inotify/doc/html/globals_eval.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li class="current"><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="globals.html"><span>All</span></a></li> - <li><a href="globals_type.html"><span>Typedefs</span></a></li> - <li><a href="globals_enum.html"><span>Enumerations</span></a></li> - <li class="current"><a href="globals_eval.html"><span>Enumerator</span></a></li> - <li><a href="globals_defs.html"><span>Defines</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>IN_MAX_EVENTS -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1">inotify-cxx.h</a> -<li>IN_MAX_INSTANCES -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9">inotify-cxx.h</a> -<li>IN_MAX_WATCHES -: <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429">inotify-cxx.h</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/globals_type.html b/shared/inotify/doc/html/globals_type.html deleted file mode 100644 index 3e2f0b63..00000000 --- a/shared/inotify/doc/html/globals_type.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Class Members</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li class="current"><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="globals.html"><span>All</span></a></li> - <li class="current"><a href="globals_type.html"><span>Typedefs</span></a></li> - <li><a href="globals_enum.html"><span>Enumerations</span></a></li> - <li><a href="globals_eval.html"><span>Enumerator</span></a></li> - <li><a href="globals_defs.html"><span>Defines</span></a></li> - </ul> - </div> -</div> -<div class="contents"> - -<p> -<ul> -<li>IN_WATCH_MAP -: <a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">inotify-cxx.h</a> -<li>IN_WP_MAP -: <a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">inotify-cxx.h</a> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/graph_legend.dot b/shared/inotify/doc/html/graph_legend.dot deleted file mode 100644 index 9a09018a..00000000 --- a/shared/inotify/doc/html/graph_legend.dot +++ /dev/null @@ -1,22 +0,0 @@ -digraph G -{ - edge [fontname="FreeSans",fontsize="10",labelfontname="FreeSans",labelfontsize="10"]; - node [fontname="FreeSans",fontsize="10",shape=record]; - Node9 [shape="box",label="Inherited",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",fillcolor="grey75",style="filled" fontcolor="black"]; - Node10 -> Node9 [dir=back,color="midnightblue",fontsize="10",style="solid",fontname="FreeSans"]; - Node10 [shape="box",label="PublicBase",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classPublicBase.html"]; - Node11 -> Node10 [dir=back,color="midnightblue",fontsize="10",style="solid",fontname="FreeSans"]; - Node11 [shape="box",label="Truncated",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="red",URL="$classTruncated.html"]; - Node13 -> Node9 [dir=back,color="darkgreen",fontsize="10",style="solid",fontname="FreeSans"]; - Node13 [shape="box",label="ProtectedBase",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classProtectedBase.html"]; - Node14 -> Node9 [dir=back,color="firebrick4",fontsize="10",style="solid",fontname="FreeSans"]; - Node14 [shape="box",label="PrivateBase",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classPrivateBase.html"]; - Node15 -> Node9 [dir=back,color="midnightblue",fontsize="10",style="solid",fontname="FreeSans"]; - Node15 [shape="box",label="Undocumented",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="grey75"]; - Node16 -> Node9 [dir=back,color="midnightblue",fontsize="10",style="solid",fontname="FreeSans"]; - Node16 [shape="box",label="Templ< int >",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classTempl.html"]; - Node17 -> Node16 [dir=back,color="orange",fontsize="10",style="dashed",label="< int >",fontname="FreeSans"]; - Node17 [shape="box",label="Templ< T >",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classTempl.html"]; - Node18 -> Node9 [dir=back,color="darkorchid3",fontsize="10",style="dashed",label="m_usedClass",fontname="FreeSans"]; - Node18 [shape="box",label="Used",fontsize="10",height=0.2,width=0.4,fontname="FreeSans",color="black",URL="$classUsed.html"]; -} diff --git a/shared/inotify/doc/html/graph_legend.html b/shared/inotify/doc/html/graph_legend.html deleted file mode 100644 index e86c0cf9..00000000 --- a/shared/inotify/doc/html/graph_legend.html +++ /dev/null @@ -1,84 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Graph Legend</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>Graph Legend</h1>This page explains how to interpret the graphs that are generated by doxygen.<p> -Consider the following example: <div class="fragment"><pre class="fragment"><span class="comment">/*! Invisible class because of truncation */</span> -<span class="keyword">class </span>Invisible { }; -<span class="comment"></span> -<span class="comment">/*! Truncated class, inheritance relation is hidden */</span> -<span class="keyword">class </span>Truncated : <span class="keyword">public</span> Invisible { }; - -<span class="comment">/* Class not documented with doxygen comments */</span> -<span class="keyword">class </span>Undocumented { }; -<span class="comment"></span> -<span class="comment">/*! Class that is inherited using public inheritance */</span> -<span class="keyword">class </span>PublicBase : <span class="keyword">public</span> Truncated { }; -<span class="comment"></span> -<span class="comment">/*! A template class */</span> -<span class="keyword">template</span><<span class="keyword">class</span> T> <span class="keyword">class </span>Templ { }; -<span class="comment"></span> -<span class="comment">/*! Class that is inherited using protected inheritance */</span> -<span class="keyword">class </span>ProtectedBase { }; -<span class="comment"></span> -<span class="comment">/*! Class that is inherited using private inheritance */</span> -<span class="keyword">class </span>PrivateBase { }; -<span class="comment"></span> -<span class="comment">/*! Class that is used by the Inherited class */</span> -<span class="keyword">class </span>Used { }; -<span class="comment"></span> -<span class="comment">/*! Super class that inherits a number of other classes */</span> -<span class="keyword">class </span>Inherited : <span class="keyword">public</span> PublicBase, - <span class="keyword">protected</span> ProtectedBase, - <span class="keyword">private</span> PrivateBase, - <span class="keyword">public</span> Undocumented, - <span class="keyword">public</span> Templ<int> -{ - <span class="keyword">private</span>: - Used *m_usedClass; -}; -</pre></div> This will result in the following graph:<p> -<center><div align="center"> -<img src="graph_legend.png" alt="graph_legend.png"> -</div> -</center> <p> -The boxes in the above graph have the following meaning: <ul> -<li> -A filled gray box represents the struct or class for which the graph is generated. </li> -<li> -A box with a black border denotes a documented struct or class. </li> -<li> -A box with a grey border denotes an undocumented struct or class. </li> -<li> -A box with a red border denotes a documented struct or class forwhich not all inheritance/containment relations are shown. A graph is truncated if it does not fit within the specified boundaries. </li> -</ul> -The arrows have the following meaning: <ul> -<li> -A dark blue arrow is used to visualize a public inheritance relation between two classes. </li> -<li> -A dark green arrow is used for protected inheritance. </li> -<li> -A dark red arrow is used for private inheritance. </li> -<li> -A purple dashed arrow is used if a class is contained or used by another class. The arrow is labeled with the variable(s) through which the pointed class or struct is accessible. </li> -<li> -A yellow dashed arrow denotes a relation between a template instance and the template class it was instantiated from. The arrow is labeled with the template parameters of the instance. </li> -</ul> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/graph_legend.png b/shared/inotify/doc/html/graph_legend.png Binary files differdeleted file mode 100644 index 67057ca1..00000000 --- a/shared/inotify/doc/html/graph_legend.png +++ /dev/null diff --git a/shared/inotify/doc/html/index.html b/shared/inotify/doc/html/index.html deleted file mode 100644 index 94cae8a5..00000000 --- a/shared/inotify/doc/html/index.html +++ /dev/null @@ -1,24 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: Main Page</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li class="current"><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li><a href="files.html"><span>Files</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>inotify-cxx Documentation</h1> -<p> -<h3 align="center">0.7.3 </h3></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/inotify-cxx_8cpp.html b/shared/inotify/doc/html/inotify-cxx_8cpp.html deleted file mode 100644 index c307e1ca..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8cpp.html +++ /dev/null @@ -1,109 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: inotify-cxx.cpp File Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>inotify-cxx.cpp File Reference</h1>inotify C++ interface implementation -<a href="#_details">More...</a> -<p> -<code>#include <errno.h></code><br> -<code>#include <unistd.h></code><br> -<code>#include <fcntl.h></code><br> -<code>#include <fstream></code><br> -<code>#include <sys/syscall.h></code><br> -<code>#include <sys/inotify-syscalls.h></code><br> -<code>#include "<a class="el" href="inotify-cxx_8h_source.html">inotify-cxx.h</a>"</code><br> - -<p> -<div class="dynheader"> -Include dependency graph for inotify-cxx.cpp:</div> -<div class="dynsection"> -<p><center><img src="inotify-cxx_8cpp__incl.png" border="0" usemap="#inotify-cxx.cpp_map" alt=""></center> -<map name="inotify-cxx.cpp_map"> -<area shape="rect" href="inotify-cxx_8h.html" title="inotify C++ interface header" alt="" coords="640,80,731,107"></map> -</div> -<table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Defines</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8cpp.html#481097f28678020b2cbb26dd071a0085">PROCFS_INOTIFY_BASE</a> "/proc/sys/fs/inotify/"</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">procfs inotify base path <a href="#481097f28678020b2cbb26dd071a0085"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8cpp.html#6e5d8f74743466e712bbaf3b1de1e93d">DUMP_SEP</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">dump separator (between particular entries) <a href="#6e5d8f74743466e712bbaf3b1de1e93d"></a><br></td></tr> -</table> -<hr><h2>Detailed Description</h2> -inotify C++ interface implementation -<p> -inotify C++ interface<p> -Copyright (C) 2006, 2007, 2009 Lukas Jelinek <<a href="mailto:lukas@aiken.cz">lukas@aiken.cz</a>><p> -This program is free software; you can redistribute it and/or modify it under the terms of one of the following licenses:<p> -<ul> -<li>1. X11-style license (see LICENSE-X11) </li> -<li>2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) </li> -<li>3. GNU General Public License, version 2 (see LICENSE-GPL)</li> -</ul> -If you want to help with choosing the best license for you, please visit <a href="http://www.gnu.org/licenses/license-list.html.">http://www.gnu.org/licenses/license-list.html.</a><p> -Credits: Mike Frysinger (cleanup of includes) <hr><h2>Define Documentation</h2> -<a class="anchor" name="6e5d8f74743466e712bbaf3b1de1e93d"></a><!-- doxytag: member="inotify-cxx.cpp::DUMP_SEP" ref="6e5d8f74743466e712bbaf3b1de1e93d" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define DUMP_SEP </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -<b>Value:</b><div class="fragment"><pre class="fragment">({ \ - <span class="keywordflow">if</span> (!rStr.empty()) { \ - rStr.append(<span class="stringliteral">","</span>); \ - } \ - }) -</pre></div>dump separator (between particular entries) -<p> - -</div> -</div><p> -<a class="anchor" name="481097f28678020b2cbb26dd071a0085"></a><!-- doxytag: member="inotify-cxx.cpp::PROCFS_INOTIFY_BASE" ref="481097f28678020b2cbb26dd071a0085" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define PROCFS_INOTIFY_BASE "/proc/sys/fs/inotify/" </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -procfs inotify base path -<p> - -</div> -</div><p> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.map b/shared/inotify/doc/html/inotify-cxx_8cpp__incl.map deleted file mode 100644 index 7f997b6b..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$inotify-cxx_8h.html" title="inotify C++ interface header" alt="" coords="640,80,731,107"> diff --git a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.md5 b/shared/inotify/doc/html/inotify-cxx_8cpp__incl.md5 deleted file mode 100644 index 9c28c7ef..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.md5 +++ /dev/null @@ -1 +0,0 @@ -579c4ee16d330d2021fb9eb25831f079
\ No newline at end of file diff --git a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.png b/shared/inotify/doc/html/inotify-cxx_8cpp__incl.png Binary files differdeleted file mode 100644 index ce7631c7..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8cpp__incl.png +++ /dev/null diff --git a/shared/inotify/doc/html/inotify-cxx_8h.html b/shared/inotify/doc/html/inotify-cxx_8h.html deleted file mode 100644 index e189937d..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h.html +++ /dev/null @@ -1,387 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: inotify-cxx.h File Reference</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> -</div> -<div class="contents"> -<h1>inotify-cxx.h File Reference</h1>inotify C++ interface header -<a href="#_details">More...</a> -<p> -<code>#include <stdint.h></code><br> -<code>#include <string></code><br> -<code>#include <deque></code><br> -<code>#include <map></code><br> -<code>#include <sys/inotify.h></code><br> - -<p> -<div class="dynheader"> -Include dependency graph for inotify-cxx.h:</div> -<div class="dynsection"> -<p><center><img src="inotify-cxx_8h__incl.png" border="0" usemap="#inotify-cxx.h_map" alt=""></center> -</div> - -<p> -<div class="dynheader"> -This graph shows which files directly or indirectly include this file:</div> -<div class="dynsection"> -<p><center><img src="inotify-cxx_8h__dep__incl.png" border="0" usemap="#inotify-cxx.hdep_map" alt=""></center> -<map name="inotify-cxx.hdep_map"> -<area shape="rect" href="inotify-cxx_8cpp.html" title="inotify C++ interface implementation" alt="" coords="5,80,109,107"></map> -</div> - -<p> -<a href="inotify-cxx_8h_source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0"> -<tr><td></td></tr> -<tr><td colspan="2"><br><h2>Classes</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyException.html">InotifyException</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Class for inotify exceptions. <a href="classInotifyException.html#_details">More...</a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyEvent.html">InotifyEvent</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify event class <a href="classInotifyEvent.html#_details">More...</a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotifyWatch.html">InotifyWatch</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify watch class <a href="classInotifyWatch.html#_details">More...</a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">class </td><td class="memItemRight" valign="bottom"><a class="el" href="classInotify.html">Inotify</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify class <a href="classInotify.html#_details">More...</a><br></td></tr> -<tr><td colspan="2"><br><h2>Defines</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#f64b4cc985ba26f31a9cb242153a5014">INOTIFY_EVENT_SIZE</a> (sizeof(struct inotify_event))</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Event struct size. <a href="#f64b4cc985ba26f31a9cb242153a5014"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#a84911f8e42d71161b60d4a28940abb4">INOTIFY_BUFLEN</a> (1024 * (INOTIFY_EVENT_SIZE + 16))</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Event buffer length. <a href="#a84911f8e42d71161b60d4a28940abb4"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#fe6b93f7e09db7022f1f9dd102932e12">IN_EXC_MSG</a>(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Helper macro for creating exception messages. <a href="#fe6b93f7e09db7022f1f9dd102932e12"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766">IN_LOCK_DECL</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify-cxx thread safety <a href="#904d25c0fd931e1bad4f9d5cd346a766"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#981aa546075fba39715fd2f63a41f575">IN_LOCK_INIT</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#08422ec66fb587c1684afbaa575a53dd">IN_LOCK_DONE</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">IN_READ_BEGIN</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">IN_READ_END</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#5c6a5be1898ef17662795cc4b420c851">IN_READ_END_NOTHROW</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#c3a6d87ace9403f7ac58f931bbcd9599">IN_WRITE_BEGIN</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#f8aeac51b3b4ef56f1791c5c1a2e9cf5">IN_WRITE_END</a></td></tr> - -<tr><td class="memItemLeft" nowrap align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#7e68c4884137939c5e3301f40c198dc7">IN_WRITE_END_NOTHROW</a></td></tr> - -<tr><td colspan="2"><br><h2>Typedefs</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef std::map< int32_t, <br class="typebreak"> -<a class="el" href="classInotifyWatch.html">InotifyWatch</a> * > </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">IN_WATCH_MAP</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Mapping from watch descriptors to watch objects. <a href="#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a"></a><br></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef std::map< std::string, <br class="typebreak"> -<a class="el" href="classInotifyWatch.html">InotifyWatch</a> * > </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">IN_WP_MAP</a></td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">Mapping from paths to watch objects. <a href="#5dd7761ff5a6b7cc7271950aebb7ddf6"></a><br></td></tr> -<tr><td colspan="2"><br><h2>Enumerations</h2></td></tr> -<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> { <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1">IN_MAX_EVENTS</a> = 0, -<a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9">IN_MAX_INSTANCES</a> = 1, -<a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429">IN_MAX_WATCHES</a> = 2 - }</td></tr> - -<tr><td class="mdescLeft"> </td><td class="mdescRight">inotify capability/limit identifiers <a href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">More...</a><br></td></tr> -</table> -<hr><h2>Detailed Description</h2> -inotify C++ interface header -<p> -inotify C++ interface<p> -Copyright (C) 2006, 2007, 2009 Lukas Jelinek, <<a href="mailto:lukas@aiken.cz">lukas@aiken.cz</a>><p> -This program is free software; you can redistribute it and/or modify it under the terms of one of the following licenses:<p> -<ul> -<li>1. X11-style license (see LICENSE-X11) </li> -<li>2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) </li> -<li>3. GNU General Public License, version 2 (see LICENSE-GPL)</li> -</ul> -If you want to help with choosing the best license for you, please visit <a href="http://www.gnu.org/licenses/license-list.html.">http://www.gnu.org/licenses/license-list.html.</a><p> -Credits: Mike Frysinger (cleanup of includes) <hr><h2>Define Documentation</h2> -<a class="anchor" name="fe6b93f7e09db7022f1f9dd102932e12"></a><!-- doxytag: member="inotify-cxx.h::IN_EXC_MSG" ref="fe6b93f7e09db7022f1f9dd102932e12" args="(msg)" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_EXC_MSG </td> - <td>(</td> - <td class="paramtype">msg </td> - <td class="paramname"> </td> - <td> ) </td> - <td> (std::string(__PRETTY_FUNCTION__) + ": " + msg)</td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Helper macro for creating exception messages. -<p> -It prepends the message by the function name. -</div> -</div><p> -<a class="anchor" name="904d25c0fd931e1bad4f9d5cd346a766"></a><!-- doxytag: member="inotify-cxx.h::IN_LOCK_DECL" ref="904d25c0fd931e1bad4f9d5cd346a766" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_LOCK_DECL </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -inotify-cxx thread safety -<p> -If this symbol is defined you can use this interface safely threaded applications. Remember that it slightly degrades performance.<p> -Even if INOTIFY_THREAD_SAFE is defined some classes stay unsafe. If you must use them (must you?) in more than one thread concurrently you need to implement explicite locking.<p> -You need not to define INOTIFY_THREAD_SAFE in that cases where the application is multithreaded but all the inotify infrastructure will be managed only in one thread. This is the recommended way.<p> -Locking may fail (it is very rare but not impossible). In this case an exception is thrown. But if unlocking fails in case of an error it does nothing (this failure is ignored). -</div> -</div><p> -<a class="anchor" name="08422ec66fb587c1684afbaa575a53dd"></a><!-- doxytag: member="inotify-cxx.h::IN_LOCK_DONE" ref="08422ec66fb587c1684afbaa575a53dd" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_LOCK_DONE </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="981aa546075fba39715fd2f63a41f575"></a><!-- doxytag: member="inotify-cxx.h::IN_LOCK_INIT" ref="981aa546075fba39715fd2f63a41f575" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_LOCK_INIT </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="963a97dc42487e86715b4e04639b0db8"></a><!-- doxytag: member="inotify-cxx.h::IN_READ_BEGIN" ref="963a97dc42487e86715b4e04639b0db8" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_READ_BEGIN </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="0b82080ab6709175341b97e1f3c3955d"></a><!-- doxytag: member="inotify-cxx.h::IN_READ_END" ref="0b82080ab6709175341b97e1f3c3955d" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_READ_END </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="5c6a5be1898ef17662795cc4b420c851"></a><!-- doxytag: member="inotify-cxx.h::IN_READ_END_NOTHROW" ref="5c6a5be1898ef17662795cc4b420c851" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_READ_END_NOTHROW </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="c3a6d87ace9403f7ac58f931bbcd9599"></a><!-- doxytag: member="inotify-cxx.h::IN_WRITE_BEGIN" ref="c3a6d87ace9403f7ac58f931bbcd9599" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_WRITE_BEGIN </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="f8aeac51b3b4ef56f1791c5c1a2e9cf5"></a><!-- doxytag: member="inotify-cxx.h::IN_WRITE_END" ref="f8aeac51b3b4ef56f1791c5c1a2e9cf5" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_WRITE_END </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="7e68c4884137939c5e3301f40c198dc7"></a><!-- doxytag: member="inotify-cxx.h::IN_WRITE_END_NOTHROW" ref="7e68c4884137939c5e3301f40c198dc7" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define IN_WRITE_END_NOTHROW </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> - -</div> -</div><p> -<a class="anchor" name="a84911f8e42d71161b60d4a28940abb4"></a><!-- doxytag: member="inotify-cxx.h::INOTIFY_BUFLEN" ref="a84911f8e42d71161b60d4a28940abb4" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16)) </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Event buffer length. -<p> - -</div> -</div><p> -<a class="anchor" name="f64b4cc985ba26f31a9cb242153a5014"></a><!-- doxytag: member="inotify-cxx.h::INOTIFY_EVENT_SIZE" ref="f64b4cc985ba26f31a9cb242153a5014" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Event struct size. -<p> - -</div> -</div><p> -<hr><h2>Typedef Documentation</h2> -<a class="anchor" name="e6b5ebcb4e0d6a9f5ca8da26bc00cc2a"></a><!-- doxytag: member="inotify-cxx.h::IN_WATCH_MAP" ref="e6b5ebcb4e0d6a9f5ca8da26bc00cc2a" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">typedef std::map<int32_t, <a class="el" href="classInotifyWatch.html">InotifyWatch</a>*> <a class="el" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">IN_WATCH_MAP</a> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Mapping from watch descriptors to watch objects. -<p> - -</div> -</div><p> -<a class="anchor" name="5dd7761ff5a6b7cc7271950aebb7ddf6"></a><!-- doxytag: member="inotify-cxx.h::IN_WP_MAP" ref="5dd7761ff5a6b7cc7271950aebb7ddf6" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">typedef std::map<std::string, <a class="el" href="classInotifyWatch.html">InotifyWatch</a>*> <a class="el" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">IN_WP_MAP</a> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -Mapping from paths to watch objects. -<p> - -</div> -</div><p> -<hr><h2>Enumeration Type Documentation</h2> -<a class="anchor" name="bccd39d32dd83905178cf42edaae5c4d"></a><!-- doxytag: member="inotify-cxx.h::InotifyCapability_t" ref="bccd39d32dd83905178cf42edaae5c4d" args="" --> -<div class="memitem"> -<div class="memproto"> - <table class="memname"> - <tr> - <td class="memname">enum <a class="el" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">InotifyCapability_t</a> </td> - </tr> - </table> -</div> -<div class="memdoc"> - -<p> -inotify capability/limit identifiers -<p> -<dl compact><dt><b>Enumerator: </b></dt><dd> -<table border="0" cellspacing="2" cellpadding="0"> -<tr><td valign="top"><em><a class="anchor" name="bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1"></a><!-- doxytag: member="IN_MAX_EVENTS" ref="bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1" args="" -->IN_MAX_EVENTS</em> </td><td> -max. events in the kernel queue </td></tr> -<tr><td valign="top"><em><a class="anchor" name="bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9"></a><!-- doxytag: member="IN_MAX_INSTANCES" ref="bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9" args="" -->IN_MAX_INSTANCES</em> </td><td> -max. inotify file descriptors per process </td></tr> -<tr><td valign="top"><em><a class="anchor" name="bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429"></a><!-- doxytag: member="IN_MAX_WATCHES" ref="bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429" args="" -->IN_MAX_WATCHES</em> </td><td> -max. watches per file descriptor </td></tr> -</table> -</dl> - -</div> -</div><p> -</div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.map b/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.map deleted file mode 100644 index 4ed3629d..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.map +++ /dev/null @@ -1 +0,0 @@ -<area shape="rect" href="$inotify-cxx_8cpp.html" title="inotify C++ interface implementation" alt="" coords="5,80,109,107"> diff --git a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.md5 b/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.md5 deleted file mode 100644 index c00ff796..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.md5 +++ /dev/null @@ -1 +0,0 @@ -4b9719ddb81e282b353a01d00e7fc79f
\ No newline at end of file diff --git a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.png b/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.png Binary files differdeleted file mode 100644 index 85d373cf..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__dep__incl.png +++ /dev/null diff --git a/shared/inotify/doc/html/inotify-cxx_8h__incl.map b/shared/inotify/doc/html/inotify-cxx_8h__incl.map deleted file mode 100644 index e69de29b..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__incl.map +++ /dev/null diff --git a/shared/inotify/doc/html/inotify-cxx_8h__incl.md5 b/shared/inotify/doc/html/inotify-cxx_8h__incl.md5 deleted file mode 100644 index c9425ce6..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__incl.md5 +++ /dev/null @@ -1 +0,0 @@ -98ce5d48dec51633b940ca16d76c825f
\ No newline at end of file diff --git a/shared/inotify/doc/html/inotify-cxx_8h__incl.png b/shared/inotify/doc/html/inotify-cxx_8h__incl.png Binary files differdeleted file mode 100644 index ae9be329..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h__incl.png +++ /dev/null diff --git a/shared/inotify/doc/html/inotify-cxx_8h_source.html b/shared/inotify/doc/html/inotify-cxx_8h_source.html deleted file mode 100644 index 99b4b37a..00000000 --- a/shared/inotify/doc/html/inotify-cxx_8h_source.html +++ /dev/null @@ -1,503 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> -<title>inotify-cxx: inotify-cxx.h Source File</title> -<link href="tabs.css" rel="stylesheet" type="text/css"> -<link href="doxygen.css" rel="stylesheet" type="text/css"> -</head><body> -<!-- Generated by Doxygen 1.5.9 --> -<div class="navigation" id="top"> - <div class="tabs"> - <ul> - <li><a href="index.html"><span>Main Page</span></a></li> - <li><a href="annotated.html"><span>Classes</span></a></li> - <li class="current"><a href="files.html"><span>Files</span></a></li> - </ul> - </div> - <div class="tabs"> - <ul> - <li><a href="files.html"><span>File List</span></a></li> - <li><a href="globals.html"><span>File Members</span></a></li> - </ul> - </div> -<h1>inotify-cxx.h</h1><a href="inotify-cxx_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 -<a name="l00003"></a>00003 -<a name="l00029"></a>00029 <span class="preprocessor">#ifndef _INOTIFYCXX_H_</span> -<a name="l00030"></a>00030 <span class="preprocessor"></span><span class="preprocessor">#define _INOTIFYCXX_H_</span> -<a name="l00031"></a>00031 <span class="preprocessor"></span> -<a name="l00032"></a>00032 <span class="preprocessor">#include <stdint.h></span> -<a name="l00033"></a>00033 <span class="preprocessor">#include <string></span> -<a name="l00034"></a>00034 <span class="preprocessor">#include <deque></span> -<a name="l00035"></a>00035 <span class="preprocessor">#include <map></span> -<a name="l00036"></a>00036 -<a name="l00037"></a>00037 <span class="comment">// Please ensure that the following header file takes the right place</span> -<a name="l00038"></a>00038 <span class="preprocessor">#include <sys/inotify.h></span> -<a name="l00039"></a>00039 -<a name="l00040"></a>00040 -<a name="l00042"></a><a class="code" href="inotify-cxx_8h.html#f64b4cc985ba26f31a9cb242153a5014">00042</a> <span class="preprocessor">#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))</span> -<a name="l00043"></a>00043 <span class="preprocessor"></span> -<a name="l00045"></a><a class="code" href="inotify-cxx_8h.html#a84911f8e42d71161b60d4a28940abb4">00045</a> <span class="preprocessor">#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))</span> -<a name="l00046"></a>00046 <span class="preprocessor"></span> -<a name="l00048"></a>00048 -<a name="l00051"></a><a class="code" href="inotify-cxx_8h.html#fe6b93f7e09db7022f1f9dd102932e12">00051</a> <span class="preprocessor">#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)</span> -<a name="l00052"></a>00052 <span class="preprocessor"></span> -<a name="l00054"></a><a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d">00054</a> <span class="keyword">typedef</span> <span class="keyword">enum</span> -<a name="l00055"></a>00055 { -<a name="l00056"></a><a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1">00056</a> <a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1" title="max. events in the kernel queue">IN_MAX_EVENTS</a> = 0, -<a name="l00057"></a><a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9">00057</a> <a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9" title="max. inotify file descriptors per process">IN_MAX_INSTANCES</a> = 1, -<a name="l00058"></a><a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429">00058</a> <a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429" title="max. watches per file descriptor">IN_MAX_WATCHES</a> = 2 -<a name="l00059"></a>00059 } <a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d" title="inotify capability/limit identifiers">InotifyCapability_t</a>; -<a name="l00060"></a>00060 -<a name="l00062"></a>00062 -<a name="l00080"></a>00080 <span class="preprocessor">#ifdef INOTIFY_THREAD_SAFE</span> -<a name="l00081"></a>00081 <span class="preprocessor"></span> -<a name="l00082"></a>00082 <span class="preprocessor">#include <pthread.h></span> -<a name="l00083"></a>00083 -<a name="l00084"></a>00084 <span class="preprocessor">#define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;</span> -<a name="l00085"></a>00085 <span class="preprocessor"></span> -<a name="l00086"></a>00086 <span class="preprocessor">#define IN_LOCK_INIT \</span> -<a name="l00087"></a>00087 <span class="preprocessor"> { \</span> -<a name="l00088"></a>00088 <span class="preprocessor"> pthread_rwlockattr_t attr; \</span> -<a name="l00089"></a>00089 <span class="preprocessor"> int res = 0; \</span> -<a name="l00090"></a>00090 <span class="preprocessor"> if ((res = pthread_rwlockattr_init(&attr)) != 0) \</span> -<a name="l00091"></a>00091 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \</span> -<a name="l00092"></a>00092 <span class="preprocessor"> if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \</span> -<a name="l00093"></a>00093 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \</span> -<a name="l00094"></a>00094 <span class="preprocessor"> if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \</span> -<a name="l00095"></a>00095 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \</span> -<a name="l00096"></a>00096 <span class="preprocessor"> pthread_rwlockattr_destroy(&attr); \</span> -<a name="l00097"></a>00097 <span class="preprocessor"> }</span> -<a name="l00098"></a>00098 <span class="preprocessor"></span> -<a name="l00099"></a>00099 <span class="preprocessor">#define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);</span> -<a name="l00100"></a>00100 <span class="preprocessor"></span> -<a name="l00101"></a>00101 <span class="preprocessor">#define IN_READ_BEGIN \</span> -<a name="l00102"></a>00102 <span class="preprocessor"> { \</span> -<a name="l00103"></a>00103 <span class="preprocessor"> int res = pthread_rwlock_rdlock(&__m_lock); \</span> -<a name="l00104"></a>00104 <span class="preprocessor"> if (res != 0) \</span> -<a name="l00105"></a>00105 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \</span> -<a name="l00106"></a>00106 <span class="preprocessor"> }</span> -<a name="l00107"></a>00107 <span class="preprocessor"></span> -<a name="l00108"></a>00108 <span class="preprocessor">#define IN_READ_END \</span> -<a name="l00109"></a>00109 <span class="preprocessor"> { \</span> -<a name="l00110"></a>00110 <span class="preprocessor"> int res = pthread_rwlock_unlock(&__m_lock); \</span> -<a name="l00111"></a>00111 <span class="preprocessor"> if (res != 0) \</span> -<a name="l00112"></a>00112 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \</span> -<a name="l00113"></a>00113 <span class="preprocessor"> }</span> -<a name="l00114"></a>00114 <span class="preprocessor"></span> -<a name="l00115"></a>00115 <span class="preprocessor">#define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);</span> -<a name="l00116"></a>00116 <span class="preprocessor"></span> -<a name="l00117"></a>00117 <span class="preprocessor">#define IN_WRITE_BEGIN \</span> -<a name="l00118"></a>00118 <span class="preprocessor"> { \</span> -<a name="l00119"></a>00119 <span class="preprocessor"> int res = pthread_rwlock_wrlock(&__m_lock); \</span> -<a name="l00120"></a>00120 <span class="preprocessor"> if (res != 0) \</span> -<a name="l00121"></a>00121 <span class="preprocessor"> throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \</span> -<a name="l00122"></a>00122 <span class="preprocessor"> }</span> -<a name="l00123"></a>00123 <span class="preprocessor"></span> -<a name="l00124"></a>00124 <span class="preprocessor">#define IN_WRITE_END IN_READ_END</span> -<a name="l00125"></a>00125 <span class="preprocessor"></span><span class="preprocessor">#define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW</span> -<a name="l00126"></a>00126 <span class="preprocessor"></span> -<a name="l00127"></a>00127 <span class="preprocessor">#else // INOTIFY_THREAD_SAFE</span> -<a name="l00128"></a>00128 <span class="preprocessor"></span> -<a name="l00129"></a><a class="code" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766">00129</a> <span class="preprocessor">#define IN_LOCK_DECL</span> -<a name="l00130"></a><a class="code" href="inotify-cxx_8h.html#981aa546075fba39715fd2f63a41f575">00130</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_LOCK_INIT</span> -<a name="l00131"></a><a class="code" href="inotify-cxx_8h.html#08422ec66fb587c1684afbaa575a53dd">00131</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_LOCK_DONE</span> -<a name="l00132"></a><a class="code" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">00132</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_READ_BEGIN</span> -<a name="l00133"></a><a class="code" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">00133</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_READ_END</span> -<a name="l00134"></a><a class="code" href="inotify-cxx_8h.html#5c6a5be1898ef17662795cc4b420c851">00134</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_READ_END_NOTHROW</span> -<a name="l00135"></a><a class="code" href="inotify-cxx_8h.html#c3a6d87ace9403f7ac58f931bbcd9599">00135</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_WRITE_BEGIN</span> -<a name="l00136"></a><a class="code" href="inotify-cxx_8h.html#f8aeac51b3b4ef56f1791c5c1a2e9cf5">00136</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_WRITE_END</span> -<a name="l00137"></a><a class="code" href="inotify-cxx_8h.html#7e68c4884137939c5e3301f40c198dc7">00137</a> <span class="preprocessor"></span><span class="preprocessor">#define IN_WRITE_END_NOTHROW</span> -<a name="l00138"></a>00138 <span class="preprocessor"></span> -<a name="l00139"></a>00139 <span class="preprocessor">#endif // INOTIFY_THREAD_SAFE</span> -<a name="l00140"></a>00140 <span class="preprocessor"></span> -<a name="l00141"></a>00141 -<a name="l00142"></a>00142 -<a name="l00143"></a>00143 -<a name="l00144"></a>00144 <span class="comment">// forward declaration</span> -<a name="l00145"></a>00145 <span class="keyword">class </span><a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>; -<a name="l00146"></a>00146 <span class="keyword">class </span><a class="code" href="classInotify.html" title="inotify class">Inotify</a>; -<a name="l00147"></a>00147 -<a name="l00148"></a>00148 -<a name="l00150"></a>00150 -<a name="l00158"></a><a class="code" href="classInotifyException.html">00158</a> <span class="keyword">class </span><a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a> -<a name="l00159"></a>00159 { -<a name="l00160"></a>00160 <span class="keyword">public</span>: -<a name="l00162"></a>00162 -<a name="l00167"></a><a class="code" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb">00167</a> <a class="code" href="classInotifyException.html#900dc29e5cfb3ece6c1651d04773b2bb" title="Constructor.">InotifyException</a>(<span class="keyword">const</span> std::string& rMsg = <span class="stringliteral">""</span>, <span class="keywordtype">int</span> iErr = 0, <span class="keywordtype">void</span>* pSrc = NULL) -<a name="l00168"></a>00168 : <a class="code" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c" title="message">m_msg</a>(rMsg), -<a name="l00169"></a>00169 <a class="code" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854" title="error number">m_err</a>(iErr) -<a name="l00170"></a>00170 { -<a name="l00171"></a>00171 <a class="code" href="classInotifyException.html#dd106c2255890025561245cf91fe1427" title="source">m_pSrc</a> = pSrc; -<a name="l00172"></a>00172 } -<a name="l00173"></a>00173 -<a name="l00175"></a>00175 -<a name="l00178"></a><a class="code" href="classInotifyException.html#6364ea375697356805d47cff957dd757">00178</a> <span class="keyword">inline</span> <span class="keyword">const</span> std::string& <a class="code" href="classInotifyException.html#6364ea375697356805d47cff957dd757" title="Returns the exception message.">GetMessage</a>()<span class="keyword"> const</span> -<a name="l00179"></a>00179 <span class="keyword"> </span>{ -<a name="l00180"></a>00180 <span class="keywordflow">return</span> <a class="code" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c" title="message">m_msg</a>; -<a name="l00181"></a>00181 } -<a name="l00182"></a>00182 -<a name="l00184"></a>00184 -<a name="l00189"></a><a class="code" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d">00189</a> <span class="keyword">inline</span> <span class="keywordtype">int</span> <a class="code" href="classInotifyException.html#60d885f998a6cb97d06111e6aded155d" title="Returns the exception error number.">GetErrorNumber</a>()<span class="keyword"> const</span> -<a name="l00190"></a>00190 <span class="keyword"> </span>{ -<a name="l00191"></a>00191 <span class="keywordflow">return</span> <a class="code" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854" title="error number">m_err</a>; -<a name="l00192"></a>00192 } -<a name="l00193"></a>00193 -<a name="l00195"></a>00195 -<a name="l00198"></a><a class="code" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408">00198</a> <span class="keyword">inline</span> <span class="keywordtype">void</span>* <a class="code" href="classInotifyException.html#619e8b963faebdefb283d79b5ae5c408" title="Returns the exception source.">GetSource</a>()<span class="keyword"> const</span> -<a name="l00199"></a>00199 <span class="keyword"> </span>{ -<a name="l00200"></a>00200 <span class="keywordflow">return</span> <a class="code" href="classInotifyException.html#dd106c2255890025561245cf91fe1427" title="source">m_pSrc</a>; -<a name="l00201"></a>00201 } -<a name="l00202"></a>00202 -<a name="l00203"></a>00203 <span class="keyword">protected</span>: -<a name="l00204"></a><a class="code" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c">00204</a> std::string <a class="code" href="classInotifyException.html#c113719bd6f4352e12876b2322f1c92c" title="message">m_msg</a>; -<a name="l00205"></a><a class="code" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854">00205</a> <span class="keywordtype">int</span> <a class="code" href="classInotifyException.html#aa8a163c661ce70e34b3e3e7ad700854" title="error number">m_err</a>; -<a name="l00206"></a><a class="code" href="classInotifyException.html#dd106c2255890025561245cf91fe1427">00206</a> <span class="keyword">mutable</span> <span class="keywordtype">void</span>* <a class="code" href="classInotifyException.html#dd106c2255890025561245cf91fe1427" title="source">m_pSrc</a>; -<a name="l00207"></a>00207 }; -<a name="l00208"></a>00208 -<a name="l00209"></a>00209 -<a name="l00211"></a>00211 -<a name="l00219"></a><a class="code" href="classInotifyEvent.html">00219</a> <span class="keyword">class </span><a class="code" href="classInotifyEvent.html" title="inotify event class">InotifyEvent</a> -<a name="l00220"></a>00220 { -<a name="l00221"></a>00221 <span class="keyword">public</span>: -<a name="l00223"></a>00223 -<a name="l00226"></a><a class="code" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046">00226</a> <a class="code" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046" title="Constructor.">InotifyEvent</a>() -<a name="l00227"></a>00227 : <a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a>(0), -<a name="l00228"></a>00228 <a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af" title="cookie">m_uCookie</a>(0) -<a name="l00229"></a>00229 { -<a name="l00230"></a>00230 <a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac" title="source watch">m_pWatch</a> = NULL; -<a name="l00231"></a>00231 } -<a name="l00232"></a>00232 -<a name="l00234"></a>00234 -<a name="l00241"></a><a class="code" href="classInotifyEvent.html#6d7f3fc0f51580da4a3ec2348609df64">00241</a> <a class="code" href="classInotifyEvent.html#f416dbbd4e6ddd3c0eea6cb540f0b046" title="Constructor.">InotifyEvent</a>(<span class="keyword">const</span> <span class="keyword">struct</span> inotify_event* pEvt, <a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* pWatch) -<a name="l00242"></a>00242 : <a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a>(0), -<a name="l00243"></a>00243 <a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af" title="cookie">m_uCookie</a>(0) -<a name="l00244"></a>00244 { -<a name="l00245"></a>00245 <span class="keywordflow">if</span> (pEvt != NULL) { -<a name="l00246"></a>00246 <a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a> = (uint32_t) pEvt->mask; -<a name="l00247"></a>00247 <a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af" title="cookie">m_uCookie</a> = (uint32_t) pEvt->cookie; -<a name="l00248"></a>00248 <span class="keywordflow">if</span> (pEvt->name != NULL) { -<a name="l00249"></a>00249 <a class="code" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604" title="name">m_name</a> = pEvt->len > 0 -<a name="l00250"></a>00250 ? pEvt->name -<a name="l00251"></a>00251 : <span class="stringliteral">""</span>; -<a name="l00252"></a>00252 } -<a name="l00253"></a>00253 <a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac" title="source watch">m_pWatch</a> = pWatch; -<a name="l00254"></a>00254 } -<a name="l00255"></a>00255 <span class="keywordflow">else</span> { -<a name="l00256"></a>00256 <a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac" title="source watch">m_pWatch</a> = NULL; -<a name="l00257"></a>00257 } -<a name="l00258"></a>00258 } -<a name="l00259"></a>00259 -<a name="l00261"></a><a class="code" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888">00261</a> <a class="code" href="classInotifyEvent.html#a48030da1d3a1b1741ca791c9e129888" title="Destructor.">~InotifyEvent</a>() {} -<a name="l00262"></a>00262 -<a name="l00264"></a>00264 -<a name="l00269"></a>00269 int32_t <a class="code" href="classInotifyEvent.html#463aacc1f660fbc1c39108feb2601341" title="Returns the event watch descriptor.">GetDescriptor</a>() <span class="keyword">const</span>; -<a name="l00270"></a>00270 -<a name="l00272"></a>00272 -<a name="l00277"></a><a class="code" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f">00277</a> <span class="keyword">inline</span> uint32_t <a class="code" href="classInotifyEvent.html#c7160544f6f4f24611df57a4422ac47f" title="Returns the event mask.">GetMask</a>()<span class="keyword"> const</span> -<a name="l00278"></a>00278 <span class="keyword"> </span>{ -<a name="l00279"></a>00279 <span class="keywordflow">return</span> <a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a>; -<a name="l00280"></a>00280 } -<a name="l00281"></a>00281 -<a name="l00283"></a>00283 -<a name="l00288"></a><a class="code" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb">00288</a> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">bool</span> <a class="code" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb" title="Checks a value for the event type.">IsType</a>(uint32_t uValue, uint32_t uType) -<a name="l00289"></a>00289 { -<a name="l00290"></a>00290 <span class="keywordflow">return</span> ((uValue & uType) != 0) && ((~uValue & uType) == 0); -<a name="l00291"></a>00291 } -<a name="l00292"></a>00292 -<a name="l00294"></a>00294 -<a name="l00298"></a><a class="code" href="classInotifyEvent.html#477ae71116ec393434a1f62a7170a156">00298</a> <span class="keyword">inline</span> <span class="keywordtype">bool</span> <a class="code" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb" title="Checks a value for the event type.">IsType</a>(uint32_t uType)<span class="keyword"> const</span> -<a name="l00299"></a>00299 <span class="keyword"> </span>{ -<a name="l00300"></a>00300 <span class="keywordflow">return</span> <a class="code" href="classInotifyEvent.html#309ebf3c5b131522295185a926d551bb" title="Checks a value for the event type.">IsType</a>(<a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a>, uType); -<a name="l00301"></a>00301 } -<a name="l00302"></a>00302 -<a name="l00304"></a>00304 -<a name="l00307"></a><a class="code" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17">00307</a> <span class="keyword">inline</span> uint32_t <a class="code" href="classInotifyEvent.html#7e65e49f7d0f11c71442e31d688e4b17" title="Returns the event cookie.">GetCookie</a>()<span class="keyword"> const</span> -<a name="l00308"></a>00308 <span class="keyword"> </span>{ -<a name="l00309"></a>00309 <span class="keywordflow">return</span> <a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af" title="cookie">m_uCookie</a>; -<a name="l00310"></a>00310 } -<a name="l00311"></a>00311 -<a name="l00313"></a>00313 -<a name="l00316"></a><a class="code" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a">00316</a> <span class="keyword">inline</span> uint32_t <a class="code" href="classInotifyEvent.html#30c8c2e1e490b8968ab9cb3364fe579a" title="Returns the event name length.">GetLength</a>()<span class="keyword"> const</span> -<a name="l00317"></a>00317 <span class="keyword"> </span>{ -<a name="l00318"></a>00318 <span class="keywordflow">return</span> (uint32_t) <a class="code" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604" title="name">m_name</a>.length(); -<a name="l00319"></a>00319 } -<a name="l00320"></a>00320 -<a name="l00322"></a>00322 -<a name="l00325"></a><a class="code" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097">00325</a> <span class="keyword">inline</span> <span class="keyword">const</span> std::string& <a class="code" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097" title="Returns the event name.">GetName</a>()<span class="keyword"> const</span> -<a name="l00326"></a>00326 <span class="keyword"> </span>{ -<a name="l00327"></a>00327 <span class="keywordflow">return</span> <a class="code" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604" title="name">m_name</a>; -<a name="l00328"></a>00328 } -<a name="l00329"></a>00329 -<a name="l00331"></a>00331 -<a name="l00334"></a><a class="code" href="classInotifyEvent.html#3aea2437ba8553be703d91b45247a68f">00334</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097" title="Returns the event name.">GetName</a>(std::string& rName)<span class="keyword"> const</span> -<a name="l00335"></a>00335 <span class="keyword"> </span>{ -<a name="l00336"></a>00336 rName = <a class="code" href="classInotifyEvent.html#5ab91d587bdc7ab3c18c6cdff73f3097" title="Returns the event name.">GetName</a>(); -<a name="l00337"></a>00337 } -<a name="l00338"></a>00338 -<a name="l00340"></a>00340 -<a name="l00343"></a><a class="code" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92">00343</a> <span class="keyword">inline</span> <a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* <a class="code" href="classInotifyEvent.html#979cd46f53ed674331a5a6d47d1cde92" title="Returns the source watch.">GetWatch</a>() -<a name="l00344"></a>00344 { -<a name="l00345"></a>00345 <span class="keywordflow">return</span> <a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac" title="source watch">m_pWatch</a>; -<a name="l00346"></a>00346 } -<a name="l00347"></a>00347 -<a name="l00349"></a>00349 -<a name="l00353"></a>00353 <span class="keyword">static</span> uint32_t <a class="code" href="classInotifyEvent.html#eced3a88a6dea190c5df19c2a6599010" title="Finds the appropriate mask for a name.">GetMaskByName</a>(<span class="keyword">const</span> std::string& rName); -<a name="l00354"></a>00354 -<a name="l00356"></a>00356 -<a name="l00360"></a>00360 <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5" title="Fills the string with all types contained in an event mask value.">DumpTypes</a>(uint32_t uValue, std::string& rStr); -<a name="l00361"></a>00361 -<a name="l00363"></a>00363 -<a name="l00366"></a>00366 <span class="keywordtype">void</span> <a class="code" href="classInotifyEvent.html#c08a0a26ea33dbe94aaf1ac830c103a5" title="Fills the string with all types contained in an event mask value.">DumpTypes</a>(std::string& rStr) <span class="keyword">const</span>; -<a name="l00367"></a>00367 -<a name="l00368"></a>00368 <span class="keyword">private</span>: -<a name="l00369"></a><a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa">00369</a> uint32_t <a class="code" href="classInotifyEvent.html#739a943357af0c3fafd58466803e04fa" title="mask">m_uMask</a>; -<a name="l00370"></a><a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af">00370</a> uint32_t <a class="code" href="classInotifyEvent.html#bf417d466fb0173d337cc66539ee55af" title="cookie">m_uCookie</a>; -<a name="l00371"></a><a class="code" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604">00371</a> std::string <a class="code" href="classInotifyEvent.html#6c507a3466515aedc266bdc267079604" title="name">m_name</a>; -<a name="l00372"></a><a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac">00372</a> <a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* <a class="code" href="classInotifyEvent.html#2d151cdcc547ee4ce49cfd44328d87ac" title="source watch">m_pWatch</a>; -<a name="l00373"></a>00373 }; -<a name="l00374"></a>00374 -<a name="l00375"></a>00375 -<a name="l00376"></a>00376 -<a name="l00378"></a>00378 -<a name="l00384"></a><a class="code" href="classInotifyWatch.html">00384</a> <span class="keyword">class </span><a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a> -<a name="l00385"></a>00385 { -<a name="l00386"></a>00386 <span class="keyword">public</span>: -<a name="l00388"></a>00388 -<a name="l00396"></a><a class="code" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9">00396</a> <a class="code" href="classInotifyWatch.html#c9c02f1dbd143eebd711eba03ac366e9" title="Constructor.">InotifyWatch</a>(<span class="keyword">const</span> std::string& rPath, int32_t uMask, <span class="keywordtype">bool</span> fEnabled = <span class="keyword">true</span>) -<a name="l00397"></a>00397 : <a class="code" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5" title="watched file path">m_path</a>(rPath), -<a name="l00398"></a>00398 <a class="code" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8" title="event mask">m_uMask</a>(uMask), -<a name="l00399"></a>00399 <a class="code" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a" title="watch descriptor">m_wd</a>((int32_t) -1), -<a name="l00400"></a>00400 <a class="code" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18" title="events enabled yes/no">m_fEnabled</a>(fEnabled) -<a name="l00401"></a>00401 { -<a name="l00402"></a>00402 <a class="code" href="inotify-cxx_8h.html#981aa546075fba39715fd2f63a41f575">IN_LOCK_INIT</a> -<a name="l00403"></a>00403 } -<a name="l00404"></a>00404 -<a name="l00406"></a><a class="code" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef">00406</a> <a class="code" href="classInotifyWatch.html#871c16b01aa8841b36246e5b629ecaef" title="Destructor.">~InotifyWatch</a>() -<a name="l00407"></a>00407 { -<a name="l00408"></a>00408 <a class="code" href="inotify-cxx_8h.html#08422ec66fb587c1684afbaa575a53dd">IN_LOCK_DONE</a> -<a name="l00409"></a>00409 } -<a name="l00410"></a>00410 -<a name="l00412"></a>00412 -<a name="l00415"></a><a class="code" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59">00415</a> <span class="keyword">inline</span> int32_t <a class="code" href="classInotifyWatch.html#855f982421402dd63d064dde328f2a59" title="Returns the watch descriptor.">GetDescriptor</a>()<span class="keyword"> const</span> -<a name="l00416"></a>00416 <span class="keyword"> </span>{ -<a name="l00417"></a>00417 <span class="keywordflow">return</span> <a class="code" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a" title="watch descriptor">m_wd</a>; -<a name="l00418"></a>00418 } -<a name="l00419"></a>00419 -<a name="l00421"></a>00421 -<a name="l00424"></a><a class="code" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2">00424</a> <span class="keyword">inline</span> <span class="keyword">const</span> std::string& <a class="code" href="classInotifyWatch.html#2e659c699e7d43bd0a218fe4905784d2" title="Returns the watched file path.">GetPath</a>()<span class="keyword"> const</span> -<a name="l00425"></a>00425 <span class="keyword"> </span>{ -<a name="l00426"></a>00426 <span class="keywordflow">return</span> <a class="code" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5" title="watched file path">m_path</a>; -<a name="l00427"></a>00427 } -<a name="l00428"></a>00428 -<a name="l00430"></a>00430 -<a name="l00433"></a><a class="code" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009">00433</a> <span class="keyword">inline</span> uint32_t <a class="code" href="classInotifyWatch.html#f759f9baca6f4abbbaae57e076486009" title="Returns the watch event mask.">GetMask</a>()<span class="keyword"> const</span> -<a name="l00434"></a>00434 <span class="keyword"> </span>{ -<a name="l00435"></a>00435 <span class="keywordflow">return</span> (uint32_t) <a class="code" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8" title="event mask">m_uMask</a>; -<a name="l00436"></a>00436 } -<a name="l00437"></a>00437 -<a name="l00439"></a>00439 -<a name="l00448"></a>00448 <span class="keywordtype">void</span> <a class="code" href="classInotifyWatch.html#3ad7fbc55c21b3fcd08c2d1d388e14b6" title="Sets the watch event mask.">SetMask</a>(uint32_t uMask) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00449"></a>00449 -<a name="l00451"></a>00451 -<a name="l00454"></a><a class="code" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0">00454</a> <span class="keyword">inline</span> <a class="code" href="classInotify.html" title="inotify class">Inotify</a>* <a class="code" href="classInotifyWatch.html#cbf0042d06841f9503405b104e4c35d0" title="Returns the appropriate inotify class instance.">GetInotify</a>() -<a name="l00455"></a>00455 { -<a name="l00456"></a>00456 <span class="keywordflow">return</span> <a class="code" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9" title="inotify object">m_pInotify</a>; -<a name="l00457"></a>00457 } -<a name="l00458"></a>00458 -<a name="l00460"></a>00460 -<a name="l00471"></a>00471 <span class="keywordtype">void</span> <a class="code" href="classInotifyWatch.html#a71aff8650fadff32a3c655ca50945f1" title="Enables/disables the watch.">SetEnabled</a>(<span class="keywordtype">bool</span> fEnabled) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00472"></a>00472 -<a name="l00474"></a>00474 -<a name="l00477"></a><a class="code" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324">00477</a> <span class="keyword">inline</span> <span class="keywordtype">bool</span> <a class="code" href="classInotifyWatch.html#5ab551a912e5acff6a9c74baaf9ea324" title="Checks whether the watch is enabled.">IsEnabled</a>()<span class="keyword"> const</span> -<a name="l00478"></a>00478 <span class="keyword"> </span>{ -<a name="l00479"></a>00479 <span class="keywordflow">return</span> <a class="code" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18" title="events enabled yes/no">m_fEnabled</a>; -<a name="l00480"></a>00480 } -<a name="l00481"></a>00481 -<a name="l00483"></a>00483 -<a name="l00492"></a><a class="code" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55">00492</a> <span class="keyword">inline</span> <span class="keywordtype">bool</span> <a class="code" href="classInotifyWatch.html#222c911ef0e8d6f61570489ed6042e55" title="Checks whether the watch is recursive.">IsRecursive</a>()<span class="keyword"> const</span> -<a name="l00493"></a>00493 <span class="keyword"> </span>{ -<a name="l00494"></a>00494 <span class="keywordflow">return</span> <span class="keyword">false</span>; -<a name="l00495"></a>00495 } -<a name="l00496"></a>00496 -<a name="l00497"></a>00497 <span class="keyword">private</span>: -<a name="l00498"></a><a class="code" href="classInotifyWatch.html#94bfb861dc18ca5d16abfcff90db8c86">00498</a> <span class="keyword">friend</span> <span class="keyword">class </span><a class="code" href="classInotify.html" title="inotify class">Inotify</a>; -<a name="l00499"></a>00499 -<a name="l00500"></a><a class="code" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5">00500</a> std::string <a class="code" href="classInotifyWatch.html#a63ba30ffdb8b9db27970bb1099e4db5" title="watched file path">m_path</a>; -<a name="l00501"></a><a class="code" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8">00501</a> uint32_t <a class="code" href="classInotifyWatch.html#f725ea61e3252adae6153ecb80de23a8" title="event mask">m_uMask</a>; -<a name="l00502"></a><a class="code" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a">00502</a> int32_t <a class="code" href="classInotifyWatch.html#90a78898dc850b238e713e0db284fb0a" title="watch descriptor">m_wd</a>; -<a name="l00503"></a><a class="code" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9">00503</a> <a class="code" href="classInotify.html" title="inotify class">Inotify</a>* <a class="code" href="classInotifyWatch.html#ea695aa11f6105184df1ef265be3f1b9" title="inotify object">m_pInotify</a>; -<a name="l00504"></a><a class="code" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18">00504</a> <span class="keywordtype">bool</span> <a class="code" href="classInotifyWatch.html#b0c23c89cc2996bdf6f41b8ef1f1ed18" title="events enabled yes/no">m_fEnabled</a>; -<a name="l00505"></a>00505 -<a name="l00506"></a>00506 <a class="code" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766" title="inotify-cxx thread safety">IN_LOCK_DECL</a> -<a name="l00507"></a>00507 -<a name="l00509"></a>00509 -<a name="l00514"></a>00514 <span class="keywordtype">void</span> <a class="code" href="classInotifyWatch.html#804cdc1e9579a075a60c239b202559f4" title="Disables the watch (due to removing by the kernel).">__Disable</a>(); -<a name="l00515"></a>00515 }; -<a name="l00516"></a>00516 -<a name="l00517"></a>00517 -<a name="l00519"></a><a class="code" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a">00519</a> <span class="keyword">typedef</span> std::map<int32_t, InotifyWatch*> <a class="code" href="inotify-cxx_8h.html#e6b5ebcb4e0d6a9f5ca8da26bc00cc2a" title="Mapping from watch descriptors to watch objects.">IN_WATCH_MAP</a>; -<a name="l00520"></a>00520 -<a name="l00522"></a><a class="code" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6">00522</a> <span class="keyword">typedef</span> std::map<std::string, InotifyWatch*> <a class="code" href="inotify-cxx_8h.html#5dd7761ff5a6b7cc7271950aebb7ddf6" title="Mapping from paths to watch objects.">IN_WP_MAP</a>; -<a name="l00523"></a>00523 -<a name="l00524"></a>00524 -<a name="l00526"></a>00526 -<a name="l00532"></a><a class="code" href="classInotify.html">00532</a> <span class="keyword">class </span><a class="code" href="classInotify.html" title="inotify class">Inotify</a> -<a name="l00533"></a>00533 { -<a name="l00534"></a>00534 <span class="keyword">public</span>: -<a name="l00536"></a>00536 -<a name="l00542"></a>00542 <a class="code" href="classInotify.html#a6fe6e9cb3343665eb968fcd5170cfb9" title="Constructor.">Inotify</a>() <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00543"></a>00543 -<a name="l00545"></a>00545 -<a name="l00548"></a>00548 <a class="code" href="classInotify.html#f19dd5e491395673e4798eb9dbf5f682" title="Destructor.">~Inotify</a>(); -<a name="l00549"></a>00549 -<a name="l00551"></a>00551 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#86ae86c43ea1a72f562ca46393309635" title="Removes all watches and closes the inotify device.">Close</a>(); -<a name="l00552"></a>00552 -<a name="l00554"></a>00554 -<a name="l00559"></a>00559 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch.">Add</a>(<a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* pWatch) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00560"></a>00560 -<a name="l00562"></a>00562 -<a name="l00567"></a><a class="code" href="classInotify.html#35dab56d3e10bf28b5e457871adddb58">00567</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch.">Add</a>(<a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>& rWatch) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00568"></a>00568 { -<a name="l00569"></a>00569 <a class="code" href="classInotify.html#2ef771ebaf982d76ebe19b3f5bc9cd83" title="Adds a new watch.">Add</a>(&rWatch); -<a name="l00570"></a>00570 } -<a name="l00571"></a>00571 -<a name="l00573"></a>00573 -<a name="l00580"></a>00580 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84" title="Removes a watch.">Remove</a>(<a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* pWatch) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00581"></a>00581 -<a name="l00583"></a>00583 -<a name="l00590"></a><a class="code" href="classInotify.html#ac1a52b2ff6bfec07021a44e55d496a6">00590</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84" title="Removes a watch.">Remove</a>(<a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>& rWatch) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00591"></a>00591 { -<a name="l00592"></a>00592 <a class="code" href="classInotify.html#21c39bb8e5bbc1941b945c18f9005b84" title="Removes a watch.">Remove</a>(&rWatch); -<a name="l00593"></a>00593 } -<a name="l00594"></a>00594 -<a name="l00596"></a>00596 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#bc1fd5830ca561efb69bcd2283981741" title="Removes all watches.">RemoveAll</a>(); -<a name="l00597"></a>00597 -<a name="l00599"></a>00599 -<a name="l00607"></a><a class="code" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075">00607</a> <span class="keyword">inline</span> <span class="keywordtype">size_t</span> <a class="code" href="classInotify.html#716ae90a00dd4895709ea9b8f7959075" title="Returns the count of watches.">GetWatchCount</a>()<span class="keyword"> const</span> -<a name="l00608"></a>00608 <span class="keyword"> </span>{ -<a name="l00609"></a>00609 <a class="code" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">IN_READ_BEGIN</a> -<a name="l00610"></a>00610 <span class="keywordtype">size_t</span> n = (size_t) <a class="code" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc" title="watches (by paths)">m_paths</a>.size(); -<a name="l00611"></a>00611 <a class="code" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">IN_READ_END</a> -<a name="l00612"></a>00612 <span class="keywordflow">return</span> n; -<a name="l00613"></a>00613 } -<a name="l00614"></a>00614 -<a name="l00616"></a>00616 -<a name="l00621"></a><a class="code" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063">00621</a> <span class="keyword">inline</span> <span class="keywordtype">size_t</span> <a class="code" href="classInotify.html#6f432affb46f85f7bc19661d5bc77063" title="Returns the count of enabled watches.">GetEnabledCount</a>()<span class="keyword"> const</span> -<a name="l00622"></a>00622 <span class="keyword"> </span>{ -<a name="l00623"></a>00623 <a class="code" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">IN_READ_BEGIN</a> -<a name="l00624"></a>00624 <span class="keywordtype">size_t</span> n = (size_t) <a class="code" href="classInotify.html#4d07f3a4412028d687936d2479d9a976" title="watches (by descriptors)">m_watches</a>.size(); -<a name="l00625"></a>00625 <a class="code" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">IN_READ_END</a> -<a name="l00626"></a>00626 <span class="keywordflow">return</span> n; -<a name="l00627"></a>00627 } -<a name="l00628"></a>00628 -<a name="l00630"></a>00630 -<a name="l00641"></a>00641 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#139c27c6643bb199619f3eae9b32e53b" title="Waits for inotify events.">WaitForEvents</a>(<span class="keywordtype">bool</span> fNoIntr = <span class="keyword">false</span>) throw (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00642"></a>00642 -<a name="l00644"></a>00644 -<a name="l00650"></a><a class="code" href="classInotify.html#a3c533f956871f904949832ac8f5fbde">00650</a> inline <span class="keywordtype">size_t</span> <a class="code" href="classInotify.html#a3c533f956871f904949832ac8f5fbde" title="Returns the count of received and queued events.">GetEventCount</a>() -<a name="l00651"></a>00651 { -<a name="l00652"></a>00652 <a class="code" href="inotify-cxx_8h.html#963a97dc42487e86715b4e04639b0db8">IN_READ_BEGIN</a> -<a name="l00653"></a>00653 <span class="keywordtype">size_t</span> n = (size_t) <a class="code" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0" title="event queue">m_events</a>.size(); -<a name="l00654"></a>00654 <a class="code" href="inotify-cxx_8h.html#0b82080ab6709175341b97e1f3c3955d">IN_READ_END</a> -<a name="l00655"></a>00655 <span class="keywordflow">return</span> n; -<a name="l00656"></a>00656 } -<a name="l00657"></a>00657 -<a name="l00659"></a>00659 -<a name="l00667"></a>00667 <span class="keywordtype">bool</span> <a class="code" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008" title="Extracts a queued inotify event.">GetEvent</a>(<a class="code" href="classInotifyEvent.html" title="inotify event class">InotifyEvent</a>* pEvt) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00668"></a>00668 -<a name="l00670"></a>00670 -<a name="l00677"></a><a class="code" href="classInotify.html#b028c8fa988f6bbb2ef773db3ea3a2d3">00677</a> <span class="keywordtype">bool</span> <a class="code" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008" title="Extracts a queued inotify event.">GetEvent</a>(<a class="code" href="classInotifyEvent.html" title="inotify event class">InotifyEvent</a>& rEvt) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00678"></a>00678 { -<a name="l00679"></a>00679 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#490a3f824c6d041d31ccaabe9bd92008" title="Extracts a queued inotify event.">GetEvent</a>(&rEvt); -<a name="l00680"></a>00680 } -<a name="l00681"></a>00681 -<a name="l00683"></a>00683 -<a name="l00691"></a>00691 <span class="keywordtype">bool</span> <a class="code" href="classInotify.html#19cde43d082ff92bd02654610019300d" title="Extracts a queued inotify event (without removing).">PeekEvent</a>(<a class="code" href="classInotifyEvent.html" title="inotify event class">InotifyEvent</a>* pEvt) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00692"></a>00692 -<a name="l00694"></a>00694 -<a name="l00701"></a><a class="code" href="classInotify.html#287dc0d238fa6edc3269441cb284f979">00701</a> <span class="keywordtype">bool</span> <a class="code" href="classInotify.html#19cde43d082ff92bd02654610019300d" title="Extracts a queued inotify event (without removing).">PeekEvent</a>(<a class="code" href="classInotifyEvent.html" title="inotify event class">InotifyEvent</a>& rEvt) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00702"></a>00702 { -<a name="l00703"></a>00703 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#19cde43d082ff92bd02654610019300d" title="Extracts a queued inotify event (without removing).">PeekEvent</a>(&rEvt); -<a name="l00704"></a>00704 } -<a name="l00705"></a>00705 -<a name="l00707"></a>00707 -<a name="l00713"></a>00713 <a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* <a class="code" href="classInotify.html#182d19b667c9e0899802b70a579eff40" title="Searches for a watch by a watch descriptor.">FindWatch</a>(<span class="keywordtype">int</span> iDescriptor); -<a name="l00714"></a>00714 -<a name="l00716"></a>00716 -<a name="l00726"></a>00726 <a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>* <a class="code" href="classInotify.html#182d19b667c9e0899802b70a579eff40" title="Searches for a watch by a watch descriptor.">FindWatch</a>(<span class="keyword">const</span> std::string& rPath); -<a name="l00727"></a>00727 -<a name="l00729"></a>00729 -<a name="l00737"></a><a class="code" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9">00737</a> <span class="keyword">inline</span> <span class="keywordtype">int</span> <a class="code" href="classInotify.html#abab7015203bf36d0256e75d4f4861f9" title="Returns the file descriptor.">GetDescriptor</a>()<span class="keyword"> const</span> -<a name="l00738"></a>00738 <span class="keyword"> </span>{ -<a name="l00739"></a>00739 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b" title="file descriptor">m_fd</a>; -<a name="l00740"></a>00740 } -<a name="l00741"></a>00741 -<a name="l00743"></a>00743 -<a name="l00756"></a>00756 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#b2c8ab8ad4322fb6f0dae0eae442402b" title="Enables/disables non-blocking mode.">SetNonBlock</a>(<span class="keywordtype">bool</span> fNonBlock) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00757"></a>00757 -<a name="l00759"></a>00759 -<a name="l00772"></a>00772 <span class="keywordtype">void</span> <a class="code" href="classInotify.html#124dd5816205900af61034d47ae65255" title="Enables/disables closing on exec.">SetCloseOnExec</a>(<span class="keywordtype">bool</span> fClOnEx) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00773"></a>00773 -<a name="l00775"></a>00775 -<a name="l00780"></a>00780 <span class="keyword">static</span> uint32_t <a class="code" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b" title="Acquires a particular inotify capability/limit.">GetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d" title="inotify capability/limit identifiers">InotifyCapability_t</a> cap) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00781"></a>00781 -<a name="l00783"></a>00783 -<a name="l00791"></a>00791 <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#734538233ba2136164f76f4df6c3654e" title="Modifies a particular inotify capability/limit.">SetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d" title="inotify capability/limit identifiers">InotifyCapability_t</a> cap, uint32_t val) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00792"></a>00792 -<a name="l00794"></a>00794 -<a name="l00798"></a><a class="code" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42">00798</a> <span class="keyword">inline</span> <span class="keyword">static</span> uint32_t <a class="code" href="classInotify.html#d8e4a4a87d005c71c0b5ea9c6dd53c42" title="Returns the maximum number of events in the kernel queue.">GetMaxEvents</a>() throw (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00799"></a>00799 { -<a name="l00800"></a>00800 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b" title="Acquires a particular inotify capability/limit.">GetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1" title="max. events in the kernel queue">IN_MAX_EVENTS</a>); -<a name="l00801"></a>00801 } -<a name="l00802"></a>00802 -<a name="l00804"></a>00804 -<a name="l00812"></a><a class="code" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9">00812</a> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#66d90ebfa516d4bd1463749def2b58f9" title="Sets the maximum number of events in the kernel queue.">SetMaxEvents</a>(uint32_t val) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00813"></a>00813 { -<a name="l00814"></a>00814 <a class="code" href="classInotify.html#734538233ba2136164f76f4df6c3654e" title="Modifies a particular inotify capability/limit.">SetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d18e969c9c44523b38a13b0a207286dd1" title="max. events in the kernel queue">IN_MAX_EVENTS</a>, val); -<a name="l00815"></a>00815 } -<a name="l00816"></a>00816 -<a name="l00818"></a>00818 -<a name="l00825"></a><a class="code" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51">00825</a> <span class="keyword">inline</span> <span class="keyword">static</span> uint32_t <a class="code" href="classInotify.html#c18b7732f67832260fbbd47aebb8af51" title="Returns the maximum number of inotify instances per process.">GetMaxInstances</a>() throw (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00826"></a>00826 { -<a name="l00827"></a>00827 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b" title="Acquires a particular inotify capability/limit.">GetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9" title="max. inotify file descriptors per process">IN_MAX_INSTANCES</a>); -<a name="l00828"></a>00828 } -<a name="l00829"></a>00829 -<a name="l00831"></a>00831 -<a name="l00839"></a><a class="code" href="classInotify.html#620c891962fe5acd26485c64e9b28d19">00839</a> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#620c891962fe5acd26485c64e9b28d19" title="Sets the maximum number of inotify instances per process.">SetMaxInstances</a>(uint32_t val) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00840"></a>00840 { -<a name="l00841"></a>00841 <a class="code" href="classInotify.html#734538233ba2136164f76f4df6c3654e" title="Modifies a particular inotify capability/limit.">SetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d43cc45296a9afe5cb68f568176608dd9" title="max. inotify file descriptors per process">IN_MAX_INSTANCES</a>, val); -<a name="l00842"></a>00842 } -<a name="l00843"></a>00843 -<a name="l00845"></a>00845 -<a name="l00852"></a><a class="code" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f">00852</a> <span class="keyword">inline</span> <span class="keyword">static</span> uint32_t <a class="code" href="classInotify.html#86dae1b7a72c0d8fc2a632444a0f2f1f" title="Returns the maximum number of inotify watches per instance.">GetMaxWatches</a>() throw (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00853"></a>00853 { -<a name="l00854"></a>00854 <span class="keywordflow">return</span> <a class="code" href="classInotify.html#70b3b57e8661fbb4c5bc404b86225c3b" title="Acquires a particular inotify capability/limit.">GetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429" title="max. watches per file descriptor">IN_MAX_WATCHES</a>); -<a name="l00855"></a>00855 } -<a name="l00856"></a>00856 -<a name="l00858"></a>00858 -<a name="l00866"></a><a class="code" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a">00866</a> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classInotify.html#5064380cdb4a726ab33f3fa18d15c77a" title="Sets the maximum number of inotify watches per instance.">SetMaxWatches</a>(uint32_t val) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>) -<a name="l00867"></a>00867 { -<a name="l00868"></a>00868 <a class="code" href="classInotify.html#734538233ba2136164f76f4df6c3654e" title="Modifies a particular inotify capability/limit.">SetCapability</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d594390780d2bdcec064c00aec1f20429" title="max. watches per file descriptor">IN_MAX_WATCHES</a>, val); -<a name="l00869"></a>00869 } -<a name="l00870"></a>00870 -<a name="l00871"></a>00871 <span class="keyword">private</span>: -<a name="l00872"></a><a class="code" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b">00872</a> <span class="keywordtype">int</span> <a class="code" href="classInotify.html#95d6d0ecefff77bd3ee50f1586a4552b" title="file descriptor">m_fd</a>; -<a name="l00873"></a><a class="code" href="classInotify.html#4d07f3a4412028d687936d2479d9a976">00873</a> IN_WATCH_MAP <a class="code" href="classInotify.html#4d07f3a4412028d687936d2479d9a976" title="watches (by descriptors)">m_watches</a>; -<a name="l00874"></a><a class="code" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc">00874</a> IN_WP_MAP <a class="code" href="classInotify.html#62f275db6375a366023b2e46f73e3ecc" title="watches (by paths)">m_paths</a>; -<a name="l00875"></a><a class="code" href="classInotify.html#eee7847efd93b681fddac56860fc7958">00875</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> <a class="code" href="classInotify.html#eee7847efd93b681fddac56860fc7958" title="buffer for events">m_buf</a>[<a class="code" href="inotify-cxx_8h.html#a84911f8e42d71161b60d4a28940abb4" title="Event buffer length.">INOTIFY_BUFLEN</a>]; -<a name="l00876"></a><a class="code" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0">00876</a> std::deque<InotifyEvent> <a class="code" href="classInotify.html#0c1d6c969292dbb7c8c1283a3d8f55e0" title="event queue">m_events</a>; -<a name="l00877"></a>00877 -<a name="l00878"></a>00878 <a class="code" href="inotify-cxx_8h.html#904d25c0fd931e1bad4f9d5cd346a766" title="inotify-cxx thread safety">IN_LOCK_DECL</a> -<a name="l00879"></a>00879 -<a name="l00880"></a><a class="code" href="classInotify.html#10880f490c33acd8bd24664fc7bce4ae">00880</a> <span class="keyword">friend</span> <span class="keyword">class </span><a class="code" href="classInotifyWatch.html" title="inotify watch class">InotifyWatch</a>; -<a name="l00881"></a>00881 -<a name="l00882"></a>00882 <span class="keyword">static</span> std::string <a class="code" href="classInotify.html#0233ddfe40844d729505fdfd709d22cc">GetCapabilityPath</a>(<a class="code" href="inotify-cxx_8h.html#bccd39d32dd83905178cf42edaae5c4d" title="inotify capability/limit identifiers">InotifyCapability_t</a> cap) <span class="keywordflow">throw</span> (<a class="code" href="classInotifyException.html" title="Class for inotify exceptions.">InotifyException</a>); -<a name="l00883"></a>00883 }; -<a name="l00884"></a>00884 -<a name="l00885"></a>00885 -<a name="l00886"></a>00886 <span class="preprocessor">#endif //_INOTIFYCXX_H_</span> -<a name="l00887"></a>00887 <span class="preprocessor"></span> -</pre></div></div> -<hr size="1"><address style="text-align: right;"><small><a href="http://www.doxygen.org/index.html"> -<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> </small></address> -</body> -</html> diff --git a/shared/inotify/doc/html/tab_b.gif b/shared/inotify/doc/html/tab_b.gif Binary files differdeleted file mode 100644 index 0d623483..00000000 --- a/shared/inotify/doc/html/tab_b.gif +++ /dev/null diff --git a/shared/inotify/doc/html/tab_l.gif b/shared/inotify/doc/html/tab_l.gif Binary files differdeleted file mode 100644 index 9b1e6337..00000000 --- a/shared/inotify/doc/html/tab_l.gif +++ /dev/null diff --git a/shared/inotify/doc/html/tab_r.gif b/shared/inotify/doc/html/tab_r.gif Binary files differdeleted file mode 100644 index ce9dd9f5..00000000 --- a/shared/inotify/doc/html/tab_r.gif +++ /dev/null diff --git a/shared/inotify/doc/html/tabs.css b/shared/inotify/doc/html/tabs.css deleted file mode 100644 index ab02c624..00000000 --- a/shared/inotify/doc/html/tabs.css +++ /dev/null @@ -1,105 +0,0 @@ -/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ - -DIV.tabs -{ - float : left; - width : 100%; - background : url("tab_b.gif") repeat-x bottom; - margin-bottom : 4px; -} - -DIV.tabs UL -{ - margin : 0px; - padding-left : 10px; - list-style : none; -} - -DIV.tabs LI, DIV.tabs FORM -{ - display : inline; - margin : 0px; - padding : 0px; -} - -DIV.tabs FORM -{ - float : right; -} - -DIV.tabs A -{ - float : left; - background : url("tab_r.gif") no-repeat right top; - border-bottom : 1px solid #84B0C7; - font-size : 80%; - font-weight : bold; - text-decoration : none; -} - -DIV.tabs A:hover -{ - background-position: 100% -150px; -} - -DIV.tabs A:link, DIV.tabs A:visited, -DIV.tabs A:active, DIV.tabs A:hover -{ - color: #1A419D; -} - -DIV.tabs SPAN -{ - float : left; - display : block; - background : url("tab_l.gif") no-repeat left top; - padding : 5px 9px; - white-space : nowrap; -} - -DIV.tabs INPUT -{ - float : right; - display : inline; - font-size : 1em; -} - -DIV.tabs TD -{ - font-size : 80%; - font-weight : bold; - text-decoration : none; -} - - - -/* Commented Backslash Hack hides rule from IE5-Mac \*/ -DIV.tabs SPAN {float : none;} -/* End IE5-Mac hack */ - -DIV.tabs A:hover SPAN -{ - background-position: 0% -150px; -} - -DIV.tabs LI.current A -{ - background-position: 100% -150px; - border-width : 0px; -} - -DIV.tabs LI.current SPAN -{ - background-position: 0% -150px; - padding-bottom : 6px; -} - -DIV.navpath -{ - background : none; - border : none; - border-bottom : 1px solid #84B0C7; - text-align : center; - margin : 2px; - padding : 2px; -} diff --git a/shared/inotify/doc/man/man3/Inotify.3 b/shared/inotify/doc/man/man3/Inotify.3 deleted file mode 100644 index 84579325..00000000 --- a/shared/inotify/doc/man/man3/Inotify.3 +++ /dev/null @@ -1,696 +0,0 @@ -.TH "Inotify" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -Inotify \- inotify class - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <inotify-cxx.h>\fP -.PP -.SS "Public Member Functions" - -.in +1c -.ti -1c -.RI "\fBInotify\fP () throw (InotifyException)" -.br -.RI "\fIConstructor. \fP" -.ti -1c -.RI "\fB~Inotify\fP ()" -.br -.RI "\fIDestructor. \fP" -.ti -1c -.RI "void \fBClose\fP ()" -.br -.RI "\fIRemoves all watches and closes the inotify device. \fP" -.ti -1c -.RI "void \fBAdd\fP (\fBInotifyWatch\fP *pWatch) throw (InotifyException)" -.br -.RI "\fIAdds a new watch. \fP" -.ti -1c -.RI "void \fBAdd\fP (\fBInotifyWatch\fP &rWatch) throw (InotifyException)" -.br -.RI "\fIAdds a new watch. \fP" -.ti -1c -.RI "void \fBRemove\fP (\fBInotifyWatch\fP *pWatch) throw (InotifyException)" -.br -.RI "\fIRemoves a watch. \fP" -.ti -1c -.RI "void \fBRemove\fP (\fBInotifyWatch\fP &rWatch) throw (InotifyException)" -.br -.RI "\fIRemoves a watch. \fP" -.ti -1c -.RI "void \fBRemoveAll\fP ()" -.br -.RI "\fIRemoves all watches. \fP" -.ti -1c -.RI "size_t \fBGetWatchCount\fP () const " -.br -.RI "\fIReturns the count of watches. \fP" -.ti -1c -.RI "size_t \fBGetEnabledCount\fP () const " -.br -.RI "\fIReturns the count of enabled watches. \fP" -.ti -1c -.RI "void \fBWaitForEvents\fP (bool fNoIntr=false) throw (InotifyException)" -.br -.RI "\fIWaits for inotify events. \fP" -.ti -1c -.RI "size_t \fBGetEventCount\fP ()" -.br -.RI "\fIReturns the count of received and queued events. \fP" -.ti -1c -.RI "bool \fBGetEvent\fP (\fBInotifyEvent\fP *pEvt) throw (InotifyException)" -.br -.RI "\fIExtracts a queued inotify event. \fP" -.ti -1c -.RI "bool \fBGetEvent\fP (\fBInotifyEvent\fP &rEvt) throw (InotifyException)" -.br -.RI "\fIExtracts a queued inotify event. \fP" -.ti -1c -.RI "bool \fBPeekEvent\fP (\fBInotifyEvent\fP *pEvt) throw (InotifyException)" -.br -.RI "\fIExtracts a queued inotify event (without removing). \fP" -.ti -1c -.RI "bool \fBPeekEvent\fP (\fBInotifyEvent\fP &rEvt) throw (InotifyException)" -.br -.RI "\fIExtracts a queued inotify event (without removing). \fP" -.ti -1c -.RI "\fBInotifyWatch\fP * \fBFindWatch\fP (int iDescriptor)" -.br -.RI "\fISearches for a watch by a watch descriptor. \fP" -.ti -1c -.RI "\fBInotifyWatch\fP * \fBFindWatch\fP (const std::string &rPath)" -.br -.RI "\fISearches for a watch by a filesystem path. \fP" -.ti -1c -.RI "int \fBGetDescriptor\fP () const " -.br -.RI "\fIReturns the file descriptor. \fP" -.ti -1c -.RI "void \fBSetNonBlock\fP (bool fNonBlock) throw (InotifyException)" -.br -.RI "\fIEnables/disables non-blocking mode. \fP" -.ti -1c -.RI "void \fBSetCloseOnExec\fP (bool fClOnEx) throw (InotifyException)" -.br -.RI "\fIEnables/disables closing on exec. \fP" -.in -1c -.SS "Static Public Member Functions" - -.in +1c -.ti -1c -.RI "static uint32_t \fBGetCapability\fP (\fBInotifyCapability_t\fP cap) throw (InotifyException)" -.br -.RI "\fIAcquires a particular inotify capability/limit. \fP" -.ti -1c -.RI "static void \fBSetCapability\fP (\fBInotifyCapability_t\fP cap, uint32_t val) throw (InotifyException)" -.br -.RI "\fIModifies a particular inotify capability/limit. \fP" -.ti -1c -.RI "static uint32_t \fBGetMaxEvents\fP () throw (InotifyException)" -.br -.RI "\fIReturns the maximum number of events in the kernel queue. \fP" -.ti -1c -.RI "static void \fBSetMaxEvents\fP (uint32_t val) throw (InotifyException)" -.br -.RI "\fISets the maximum number of events in the kernel queue. \fP" -.ti -1c -.RI "static uint32_t \fBGetMaxInstances\fP () throw (InotifyException)" -.br -.RI "\fIReturns the maximum number of inotify instances per process. \fP" -.ti -1c -.RI "static void \fBSetMaxInstances\fP (uint32_t val) throw (InotifyException)" -.br -.RI "\fISets the maximum number of inotify instances per process. \fP" -.ti -1c -.RI "static uint32_t \fBGetMaxWatches\fP () throw (InotifyException)" -.br -.RI "\fIReturns the maximum number of inotify watches per instance. \fP" -.ti -1c -.RI "static void \fBSetMaxWatches\fP (uint32_t val) throw (InotifyException)" -.br -.RI "\fISets the maximum number of inotify watches per instance. \fP" -.in -1c -.SS "Static Private Member Functions" - -.in +1c -.ti -1c -.RI "static std::string \fBGetCapabilityPath\fP (\fBInotifyCapability_t\fP cap) throw (InotifyException)" -.br -.in -1c -.SS "Private Attributes" - -.in +1c -.ti -1c -.RI "int \fBm_fd\fP" -.br -.RI "\fIfile descriptor \fP" -.ti -1c -.RI "\fBIN_WATCH_MAP\fP \fBm_watches\fP" -.br -.RI "\fIwatches (by descriptors) \fP" -.ti -1c -.RI "\fBIN_WP_MAP\fP \fBm_paths\fP" -.br -.RI "\fIwatches (by paths) \fP" -.ti -1c -.RI "unsigned char \fBm_buf\fP [INOTIFY_BUFLEN]" -.br -.RI "\fIbuffer for events \fP" -.ti -1c -.RI "std::deque< \fBInotifyEvent\fP > \fBm_events\fP" -.br -.RI "\fIevent queue \fP" -.in -1c -.SS "Friends" - -.in +1c -.ti -1c -.RI "class \fBInotifyWatch\fP" -.br -.in -1c -.SH "Detailed Description" -.PP -inotify class - -It holds information about the inotify device descriptor and manages the event queue. -.PP -If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. -.SH "Constructor & Destructor Documentation" -.PP -.SS "Inotify::Inotify () throw (\fBInotifyException\fP)" -.PP -Constructor. -.PP -Creates and initializes an instance of inotify communication object (opens the inotify device). -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if inotify isn't available -.RE -.PP - -.SS "Inotify::~Inotify ()" -.PP -Destructor. -.PP -Calls \fBClose()\fP due to clean-up. -.SH "Member Function Documentation" -.PP -.SS "void Inotify::Add (\fBInotifyWatch\fP & rWatch) throw (\fBInotifyException\fP)\fC [inline]\fP" -.PP -Adds a new watch. -.PP -\fBParameters:\fP -.RS 4 -\fIrWatch\fP inotify watch -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if adding failed -.RE -.PP - -.SS "void Inotify::Add (\fBInotifyWatch\fP * pWatch) throw (\fBInotifyException\fP)" -.PP -Adds a new watch. -.PP -\fBParameters:\fP -.RS 4 -\fIpWatch\fP inotify watch -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if adding failed -.RE -.PP - -.SS "void Inotify::Close ()" -.PP -Removes all watches and closes the inotify device. -.PP -.SS "\fBInotifyWatch\fP * Inotify::FindWatch (const std::string & rPath)" -.PP -Searches for a watch by a filesystem path. -.PP -It tries to find a watch by the given filesystem path. -.PP -\fBParameters:\fP -.RS 4 -\fIrPath\fP filesystem path -.RE -.PP -\fBReturns:\fP -.RS 4 -pointer to a watch; NULL if no such watch exists -.RE -.PP -\fBAttention:\fP -.RS 4 -The path must be exactly identical to the one used for the searched watch. Be careful about absolute/relative and case-insensitive paths. -.RE -.PP - -.SS "\fBInotifyWatch\fP * Inotify::FindWatch (int iDescriptor)" -.PP -Searches for a watch by a watch descriptor. -.PP -It tries to find a watch by the given descriptor. -.PP -\fBParameters:\fP -.RS 4 -\fIiDescriptor\fP watch descriptor -.RE -.PP -\fBReturns:\fP -.RS 4 -pointer to a watch; NULL if no such watch exists -.RE -.PP - -.SS "uint32_t Inotify::GetCapability (\fBInotifyCapability_t\fP cap) throw (\fBInotifyException\fP)\fC [static]\fP" -.PP -Acquires a particular inotify capability/limit. -.PP -\fBParameters:\fP -.RS 4 -\fIcap\fP capability/limit identifier -.RE -.PP -\fBReturns:\fP -.RS 4 -capability/limit value -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be acquired -.RE -.PP - -.SS "std::string Inotify::GetCapabilityPath (\fBInotifyCapability_t\fP cap) throw (\fBInotifyException\fP)\fC [static, private]\fP" -.PP -.SS "int Inotify::GetDescriptor () const\fC [inline]\fP" -.PP -Returns the file descriptor. -.PP -The descriptor can be used in standard low-level file functions (poll(), select(), fcntl() etc.). -.PP -\fBReturns:\fP -.RS 4 -valid file descriptor or -1 for inactive object -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBSetNonBlock()\fP -.RE -.PP - -.SS "size_t Inotify::GetEnabledCount () const\fC [inline]\fP" -.PP -Returns the count of enabled watches. -.PP -\fBReturns:\fP -.RS 4 -count of enabled watches -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBGetWatchCount()\fP -.RE -.PP - -.SS "bool Inotify::GetEvent (\fBInotifyEvent\fP & rEvt) throw (\fBInotifyException\fP)\fC [inline]\fP" -.PP -Extracts a queued inotify event. -.PP -The extracted event is removed from the queue. -.PP -\fBParameters:\fP -.RS 4 -\fIrEvt\fP event object -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown only in very anomalous cases -.RE -.PP - -.SS "bool Inotify::GetEvent (\fBInotifyEvent\fP * pEvt) throw (\fBInotifyException\fP)" -.PP -Extracts a queued inotify event. -.PP -The extracted event is removed from the queue. If the pointer is NULL it does nothing. -.PP -\fBParameters:\fP -.RS 4 -\fIpEvt\fP event object -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the provided pointer is NULL -.RE -.PP - -.SS "size_t Inotify::GetEventCount ()\fC [inline]\fP" -.PP -Returns the count of received and queued events. -.PP -This number is related to the events in the queue inside this object, not to the events pending in the kernel. -.PP -\fBReturns:\fP -.RS 4 -count of events -.RE -.PP - -.SS "static uint32_t Inotify::GetMaxEvents () throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Returns the maximum number of events in the kernel queue. -.PP -\fBReturns:\fP -.RS 4 -maximum number of events in the kernel queue -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be acquired -.RE -.PP - -.SS "static uint32_t Inotify::GetMaxInstances () throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Returns the maximum number of inotify instances per process. -.PP -It means the maximum number of open inotify file descriptors per running process. -.PP -\fBReturns:\fP -.RS 4 -maximum number of inotify instances -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be acquired -.RE -.PP - -.SS "static uint32_t Inotify::GetMaxWatches () throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Returns the maximum number of inotify watches per instance. -.PP -It means the maximum number of inotify watches per inotify file descriptor. -.PP -\fBReturns:\fP -.RS 4 -maximum number of inotify watches -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be acquired -.RE -.PP - -.SS "size_t Inotify::GetWatchCount () const\fC [inline]\fP" -.PP -Returns the count of watches. -.PP -This is the total count of all watches (regardless whether enabled or not). -.PP -\fBReturns:\fP -.RS 4 -count of watches -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBGetEnabledCount()\fP -.RE -.PP - -.SS "bool Inotify::PeekEvent (\fBInotifyEvent\fP & rEvt) throw (\fBInotifyException\fP)\fC [inline]\fP" -.PP -Extracts a queued inotify event (without removing). -.PP -The extracted event stays in the queue. -.PP -\fBParameters:\fP -.RS 4 -\fIrEvt\fP event object -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown only in very anomalous cases -.RE -.PP - -.SS "bool Inotify::PeekEvent (\fBInotifyEvent\fP * pEvt) throw (\fBInotifyException\fP)" -.PP -Extracts a queued inotify event (without removing). -.PP -The extracted event stays in the queue. If the pointer is NULL it does nothing. -.PP -\fBParameters:\fP -.RS 4 -\fIpEvt\fP event object -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the provided pointer is NULL -.RE -.PP - -.SS "void Inotify::Remove (\fBInotifyWatch\fP & rWatch) throw (\fBInotifyException\fP)\fC [inline]\fP" -.PP -Removes a watch. -.PP -If the given watch is not present it does nothing. -.PP -\fBParameters:\fP -.RS 4 -\fIrWatch\fP inotify watch -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if removing failed -.RE -.PP - -.SS "void Inotify::Remove (\fBInotifyWatch\fP * pWatch) throw (\fBInotifyException\fP)" -.PP -Removes a watch. -.PP -If the given watch is not present it does nothing. -.PP -\fBParameters:\fP -.RS 4 -\fIpWatch\fP inotify watch -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if removing failed -.RE -.PP - -.SS "void Inotify::RemoveAll ()" -.PP -Removes all watches. -.PP -.SS "void Inotify::SetCapability (\fBInotifyCapability_t\fP cap, uint32_t val) throw (\fBInotifyException\fP)\fC [static]\fP" -.PP -Modifies a particular inotify capability/limit. -.PP -\fBParameters:\fP -.RS 4 -\fIcap\fP capability/limit identifier -.br -\fIval\fP new capability/limit value -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be set -.RE -.PP -\fBAttention:\fP -.RS 4 -Using this function requires root privileges. Beware of setting extensive values - it may seriously affect system performance and/or stability. -.RE -.PP - -.SS "void Inotify::SetCloseOnExec (bool fClOnEx) throw (\fBInotifyException\fP)" -.PP -Enables/disables closing on exec. -.PP -Enable this if you want to close the descriptor when executing another program. Otherwise, the descriptor will be inherited. -.PP -Closing on exec is disabled by default. -.PP -\fBParameters:\fP -.RS 4 -\fIfClOnEx\fP enable/disable closing on exec -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if setting failed -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBGetDescriptor()\fP, \fBSetNonBlock()\fP -.RE -.PP - -.SS "static void Inotify::SetMaxEvents (uint32_t val) throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Sets the maximum number of events in the kernel queue. -.PP -\fBParameters:\fP -.RS 4 -\fIval\fP new value -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be set -.RE -.PP -\fBAttention:\fP -.RS 4 -Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. -.RE -.PP - -.SS "static void Inotify::SetMaxInstances (uint32_t val) throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Sets the maximum number of inotify instances per process. -.PP -\fBParameters:\fP -.RS 4 -\fIval\fP new value -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be set -.RE -.PP -\fBAttention:\fP -.RS 4 -Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. -.RE -.PP - -.SS "static void Inotify::SetMaxWatches (uint32_t val) throw (\fBInotifyException\fP)\fC [inline, static]\fP" -.PP -Sets the maximum number of inotify watches per instance. -.PP -\fBParameters:\fP -.RS 4 -\fIval\fP new value -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if the given value cannot be set -.RE -.PP -\fBAttention:\fP -.RS 4 -Using this function requires root privileges. Beware of setting extensive values - the greater value is set here the more physical memory may be used for the inotify infrastructure. -.RE -.PP - -.SS "void Inotify::SetNonBlock (bool fNonBlock) throw (\fBInotifyException\fP)" -.PP -Enables/disables non-blocking mode. -.PP -Use this mode if you want to monitor the descriptor (acquired thru \fBGetDescriptor()\fP) in functions such as poll(), select() etc. -.PP -Non-blocking mode is disabled by default. -.PP -\fBParameters:\fP -.RS 4 -\fIfNonBlock\fP enable/disable non-blocking mode -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if setting mode failed -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBGetDescriptor()\fP, \fBSetCloseOnExec()\fP -.RE -.PP - -.SS "void Inotify::WaitForEvents (bool fNoIntr = \fCfalse\fP) throw (\fBInotifyException\fP)" -.PP -Waits for inotify events. -.PP -It waits until one or more events occur. When called in nonblocking mode it only retrieves occurred events to the internal queue and exits. -.PP -\fBParameters:\fP -.RS 4 -\fIfNoIntr\fP if true it re-calls the system call after a handled signal -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if reading events failed -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBSetNonBlock()\fP -.RE -.PP - -.SH "Friends And Related Function Documentation" -.PP -.SS "friend class \fBInotifyWatch\fP\fC [friend]\fP" -.PP -.SH "Member Data Documentation" -.PP -.SS "unsigned char \fBInotify::m_buf\fP[INOTIFY_BUFLEN]\fC [private]\fP" -.PP -buffer for events -.PP -.SS "std::deque<\fBInotifyEvent\fP> \fBInotify::m_events\fP\fC [private]\fP" -.PP -event queue -.PP -.SS "int \fBInotify::m_fd\fP\fC [private]\fP" -.PP -file descriptor -.PP -.SS "\fBIN_WP_MAP\fP \fBInotify::m_paths\fP\fC [private]\fP" -.PP -watches (by paths) -.PP -.SS "\fBIN_WATCH_MAP\fP \fBInotify::m_watches\fP\fC [private]\fP" -.PP -watches (by descriptors) -.PP - - -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/doc/man/man3/InotifyEvent.3 b/shared/inotify/doc/man/man3/InotifyEvent.3 deleted file mode 100644 index c45eaba9..00000000 --- a/shared/inotify/doc/man/man3/InotifyEvent.3 +++ /dev/null @@ -1,306 +0,0 @@ -.TH "InotifyEvent" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -InotifyEvent \- inotify event class - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <inotify-cxx.h>\fP -.PP -.SS "Public Member Functions" - -.in +1c -.ti -1c -.RI "\fBInotifyEvent\fP ()" -.br -.RI "\fIConstructor. \fP" -.ti -1c -.RI "\fBInotifyEvent\fP (const struct inotify_event *pEvt, \fBInotifyWatch\fP *pWatch)" -.br -.RI "\fIConstructor. \fP" -.ti -1c -.RI "\fB~InotifyEvent\fP ()" -.br -.RI "\fIDestructor. \fP" -.ti -1c -.RI "int32_t \fBGetDescriptor\fP () const " -.br -.RI "\fIReturns the event watch descriptor. \fP" -.ti -1c -.RI "uint32_t \fBGetMask\fP () const " -.br -.RI "\fIReturns the event mask. \fP" -.ti -1c -.RI "bool \fBIsType\fP (uint32_t uType) const " -.br -.RI "\fIChecks for the event type. \fP" -.ti -1c -.RI "uint32_t \fBGetCookie\fP () const " -.br -.RI "\fIReturns the event cookie. \fP" -.ti -1c -.RI "uint32_t \fBGetLength\fP () const " -.br -.RI "\fIReturns the event name length. \fP" -.ti -1c -.RI "const std::string & \fBGetName\fP () const " -.br -.RI "\fIReturns the event name. \fP" -.ti -1c -.RI "void \fBGetName\fP (std::string &rName) const " -.br -.RI "\fIExtracts the event name. \fP" -.ti -1c -.RI "\fBInotifyWatch\fP * \fBGetWatch\fP ()" -.br -.RI "\fIReturns the source watch. \fP" -.ti -1c -.RI "void \fBDumpTypes\fP (std::string &rStr) const " -.br -.RI "\fIFills the string with all types contained in the event mask. \fP" -.in -1c -.SS "Static Public Member Functions" - -.in +1c -.ti -1c -.RI "static bool \fBIsType\fP (uint32_t uValue, uint32_t uType)" -.br -.RI "\fIChecks a value for the event type. \fP" -.ti -1c -.RI "static uint32_t \fBGetMaskByName\fP (const std::string &rName)" -.br -.RI "\fIFinds the appropriate mask for a name. \fP" -.ti -1c -.RI "static void \fBDumpTypes\fP (uint32_t uValue, std::string &rStr)" -.br -.RI "\fIFills the string with all types contained in an event mask value. \fP" -.in -1c -.SS "Private Attributes" - -.in +1c -.ti -1c -.RI "uint32_t \fBm_uMask\fP" -.br -.RI "\fImask \fP" -.ti -1c -.RI "uint32_t \fBm_uCookie\fP" -.br -.RI "\fIcookie \fP" -.ti -1c -.RI "std::string \fBm_name\fP" -.br -.RI "\fIname \fP" -.ti -1c -.RI "\fBInotifyWatch\fP * \fBm_pWatch\fP" -.br -.RI "\fIsource watch \fP" -.in -1c -.SH "Detailed Description" -.PP -inotify event class - -It holds all information about inotify event and provides access to its particular values. -.PP -This class is not (and is not intended to be) thread-safe and therefore it must not be used concurrently in multiple threads. -.SH "Constructor & Destructor Documentation" -.PP -.SS "InotifyEvent::InotifyEvent ()\fC [inline]\fP" -.PP -Constructor. -.PP -Creates a plain event. -.SS "InotifyEvent::InotifyEvent (const struct inotify_event * pEvt, \fBInotifyWatch\fP * pWatch)\fC [inline]\fP" -.PP -Constructor. -.PP -Creates an event based on inotify event data. For NULL pointers it works the same way as \fBInotifyEvent()\fP. -.PP -\fBParameters:\fP -.RS 4 -\fIpEvt\fP event data -.br -\fIpWatch\fP inotify watch -.RE -.PP - -.SS "InotifyEvent::~InotifyEvent ()\fC [inline]\fP" -.PP -Destructor. -.PP -.SH "Member Function Documentation" -.PP -.SS "void InotifyEvent::DumpTypes (std::string & rStr) const" -.PP -Fills the string with all types contained in the event mask. -.PP -\fBParameters:\fP -.RS 4 -\fIrStr\fP dumped event types -.RE -.PP - -.SS "void InotifyEvent::DumpTypes (uint32_t uValue, std::string & rStr)\fC [static]\fP" -.PP -Fills the string with all types contained in an event mask value. -.PP -\fBParameters:\fP -.RS 4 -\fIuValue\fP event mask value -.br -\fIrStr\fP dumped event types -.RE -.PP - -.SS "uint32_t InotifyEvent::GetCookie () const\fC [inline]\fP" -.PP -Returns the event cookie. -.PP -\fBReturns:\fP -.RS 4 -event cookie -.RE -.PP - -.SS "int32_t InotifyEvent::GetDescriptor () const" -.PP -Returns the event watch descriptor. -.PP -\fBReturns:\fP -.RS 4 -watch descriptor -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBInotifyWatch::GetDescriptor()\fP -.RE -.PP - -.SS "uint32_t InotifyEvent::GetLength () const\fC [inline]\fP" -.PP -Returns the event name length. -.PP -\fBReturns:\fP -.RS 4 -event name length -.RE -.PP - -.SS "uint32_t InotifyEvent::GetMask () const\fC [inline]\fP" -.PP -Returns the event mask. -.PP -\fBReturns:\fP -.RS 4 -event mask -.RE -.PP -\fBSee also:\fP -.RS 4 -\fBInotifyWatch::GetMask()\fP -.RE -.PP - -.SS "uint32_t InotifyEvent::GetMaskByName (const std::string & rName)\fC [static]\fP" -.PP -Finds the appropriate mask for a name. -.PP -\fBParameters:\fP -.RS 4 -\fIrName\fP mask name -.RE -.PP -\fBReturns:\fP -.RS 4 -mask for name; 0 on failure -.RE -.PP - -.SS "void InotifyEvent::GetName (std::string & rName) const\fC [inline]\fP" -.PP -Extracts the event name. -.PP -\fBParameters:\fP -.RS 4 -\fIrName\fP event name -.RE -.PP - -.SS "const std::string& InotifyEvent::GetName () const\fC [inline]\fP" -.PP -Returns the event name. -.PP -\fBReturns:\fP -.RS 4 -event name -.RE -.PP - -.SS "\fBInotifyWatch\fP* InotifyEvent::GetWatch ()\fC [inline]\fP" -.PP -Returns the source watch. -.PP -\fBReturns:\fP -.RS 4 -source watch -.RE -.PP - -.SS "bool InotifyEvent::IsType (uint32_t uType) const\fC [inline]\fP" -.PP -Checks for the event type. -.PP -\fBParameters:\fP -.RS 4 -\fIuType\fP type which is checked for -.RE -.PP -\fBReturns:\fP -.RS 4 -true = event mask contains the given type, false = otherwise -.RE -.PP - -.SS "static bool InotifyEvent::IsType (uint32_t uValue, uint32_t uType)\fC [inline, static]\fP" -.PP -Checks a value for the event type. -.PP -\fBParameters:\fP -.RS 4 -\fIuValue\fP checked value -.br -\fIuType\fP type which is checked for -.RE -.PP -\fBReturns:\fP -.RS 4 -true = the value contains the given type, false = otherwise -.RE -.PP - -.SH "Member Data Documentation" -.PP -.SS "std::string \fBInotifyEvent::m_name\fP\fC [private]\fP" -.PP -name -.PP -.SS "\fBInotifyWatch\fP* \fBInotifyEvent::m_pWatch\fP\fC [private]\fP" -.PP -source watch -.PP -.SS "uint32_t \fBInotifyEvent::m_uCookie\fP\fC [private]\fP" -.PP -cookie -.PP -.SS "uint32_t \fBInotifyEvent::m_uMask\fP\fC [private]\fP" -.PP -mask -.PP - - -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/doc/man/man3/InotifyException.3 b/shared/inotify/doc/man/man3/InotifyException.3 deleted file mode 100644 index 57bc1bec..00000000 --- a/shared/inotify/doc/man/man3/InotifyException.3 +++ /dev/null @@ -1,124 +0,0 @@ -.TH "InotifyException" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -InotifyException \- Class for inotify exceptions. - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <inotify-cxx.h>\fP -.PP -.SS "Public Member Functions" - -.in +1c -.ti -1c -.RI "\fBInotifyException\fP (const std::string &rMsg='', int iErr=0, void *pSrc=NULL)" -.br -.RI "\fIConstructor. \fP" -.ti -1c -.RI "const std::string & \fBGetMessage\fP () const " -.br -.RI "\fIReturns the exception message. \fP" -.ti -1c -.RI "int \fBGetErrorNumber\fP () const " -.br -.RI "\fIReturns the exception error number. \fP" -.ti -1c -.RI "void * \fBGetSource\fP () const " -.br -.RI "\fIReturns the exception source. \fP" -.in -1c -.SS "Protected Attributes" - -.in +1c -.ti -1c -.RI "std::string \fBm_msg\fP" -.br -.RI "\fImessage \fP" -.ti -1c -.RI "int \fBm_err\fP" -.br -.RI "\fIerror number \fP" -.ti -1c -.RI "void * \fBm_pSrc\fP" -.br -.RI "\fIsource \fP" -.in -1c -.SH "Detailed Description" -.PP -Class for inotify exceptions. - -This class allows to acquire information about exceptional events. It makes easier to log or display error messages and to identify problematic code locations. -.PP -Although this class is basically thread-safe it is not intended to be shared between threads. -.SH "Constructor & Destructor Documentation" -.PP -.SS "InotifyException::InotifyException (const std::string & rMsg = \fC''\fP, int iErr = \fC0\fP, void * pSrc = \fCNULL\fP)\fC [inline]\fP" -.PP -Constructor. -.PP -\fBParameters:\fP -.RS 4 -\fIrMsg\fP message -.br -\fIiErr\fP error number (see errno.h) -.br -\fIpSrc\fP source -.RE -.PP - -.SH "Member Function Documentation" -.PP -.SS "int InotifyException::GetErrorNumber () const\fC [inline]\fP" -.PP -Returns the exception error number. -.PP -If not applicable this value is 0 (zero). -.PP -\fBReturns:\fP -.RS 4 -error number (standardized; see errno.h) -.RE -.PP - -.SS "const std::string& InotifyException::GetMessage () const\fC [inline]\fP" -.PP -Returns the exception message. -.PP -\fBReturns:\fP -.RS 4 -message -.RE -.PP - -.SS "void* InotifyException::GetSource () const\fC [inline]\fP" -.PP -Returns the exception source. -.PP -\fBReturns:\fP -.RS 4 -source -.RE -.PP - -.SH "Member Data Documentation" -.PP -.SS "int \fBInotifyException::m_err\fP\fC [protected]\fP" -.PP -error number -.PP -.SS "std::string \fBInotifyException::m_msg\fP\fC [protected]\fP" -.PP -message -.PP -.SS "void* \fBInotifyException::m_pSrc\fP\fC [mutable, protected]\fP" -.PP -source -.PP - - -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/doc/man/man3/InotifyWatch.3 b/shared/inotify/doc/man/man3/InotifyWatch.3 deleted file mode 100644 index cac74012..00000000 --- a/shared/inotify/doc/man/man3/InotifyWatch.3 +++ /dev/null @@ -1,265 +0,0 @@ -.TH "InotifyWatch" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -InotifyWatch \- inotify watch class - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <inotify-cxx.h>\fP -.PP -.SS "Public Member Functions" - -.in +1c -.ti -1c -.RI "\fBInotifyWatch\fP (const std::string &rPath, int32_t uMask, bool fEnabled=true)" -.br -.RI "\fIConstructor. \fP" -.ti -1c -.RI "\fB~InotifyWatch\fP ()" -.br -.RI "\fIDestructor. \fP" -.ti -1c -.RI "int32_t \fBGetDescriptor\fP () const " -.br -.RI "\fIReturns the watch descriptor. \fP" -.ti -1c -.RI "const std::string & \fBGetPath\fP () const " -.br -.RI "\fIReturns the watched file path. \fP" -.ti -1c -.RI "uint32_t \fBGetMask\fP () const " -.br -.RI "\fIReturns the watch event mask. \fP" -.ti -1c -.RI "void \fBSetMask\fP (uint32_t uMask) throw (InotifyException)" -.br -.RI "\fISets the watch event mask. \fP" -.ti -1c -.RI "\fBInotify\fP * \fBGetInotify\fP ()" -.br -.RI "\fIReturns the appropriate inotify class instance. \fP" -.ti -1c -.RI "void \fBSetEnabled\fP (bool fEnabled) throw (InotifyException)" -.br -.RI "\fIEnables/disables the watch. \fP" -.ti -1c -.RI "bool \fBIsEnabled\fP () const " -.br -.RI "\fIChecks whether the watch is enabled. \fP" -.ti -1c -.RI "bool \fBIsRecursive\fP () const " -.br -.RI "\fIChecks whether the watch is recursive. \fP" -.in -1c -.SS "Private Member Functions" - -.in +1c -.ti -1c -.RI "IN_LOCK_DECL void \fB__Disable\fP ()" -.br -.RI "\fIDisables the watch (due to removing by the kernel). \fP" -.in -1c -.SS "Private Attributes" - -.in +1c -.ti -1c -.RI "std::string \fBm_path\fP" -.br -.RI "\fIwatched file path \fP" -.ti -1c -.RI "uint32_t \fBm_uMask\fP" -.br -.RI "\fIevent mask \fP" -.ti -1c -.RI "int32_t \fBm_wd\fP" -.br -.RI "\fIwatch descriptor \fP" -.ti -1c -.RI "\fBInotify\fP * \fBm_pInotify\fP" -.br -.RI "\fIinotify object \fP" -.ti -1c -.RI "bool \fBm_fEnabled\fP" -.br -.RI "\fIevents enabled yes/no \fP" -.in -1c -.SS "Friends" - -.in +1c -.ti -1c -.RI "class \fBInotify\fP" -.br -.in -1c -.SH "Detailed Description" -.PP -inotify watch class - -It holds information about the inotify watch on a particular inode. -.PP -If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. -.SH "Constructor & Destructor Documentation" -.PP -.SS "InotifyWatch::InotifyWatch (const std::string & rPath, int32_t uMask, bool fEnabled = \fCtrue\fP)\fC [inline]\fP" -.PP -Constructor. -.PP -Creates an inotify watch. Because this watch is inactive it has an invalid descriptor (-1). -.PP -\fBParameters:\fP -.RS 4 -\fIrPath\fP watched file path -.br -\fIuMask\fP mask for events -.br -\fIfEnabled\fP events enabled yes/no -.RE -.PP - -.SS "InotifyWatch::~InotifyWatch ()\fC [inline]\fP" -.PP -Destructor. -.PP -.SH "Member Function Documentation" -.PP -.SS "void InotifyWatch::__Disable ()\fC [private]\fP" -.PP -Disables the watch (due to removing by the kernel). -.PP -This method must be called after receiving an event. It ensures the watch object is consistent with the kernel data. -.SS "int32_t InotifyWatch::GetDescriptor () const\fC [inline]\fP" -.PP -Returns the watch descriptor. -.PP -\fBReturns:\fP -.RS 4 -watch descriptor; -1 for inactive watch -.RE -.PP - -.SS "\fBInotify\fP* InotifyWatch::GetInotify ()\fC [inline]\fP" -.PP -Returns the appropriate inotify class instance. -.PP -\fBReturns:\fP -.RS 4 -inotify instance -.RE -.PP - -.SS "uint32_t InotifyWatch::GetMask () const\fC [inline]\fP" -.PP -Returns the watch event mask. -.PP -\fBReturns:\fP -.RS 4 -event mask -.RE -.PP - -.SS "const std::string& InotifyWatch::GetPath () const\fC [inline]\fP" -.PP -Returns the watched file path. -.PP -\fBReturns:\fP -.RS 4 -file path -.RE -.PP - -.SS "bool InotifyWatch::IsEnabled () const\fC [inline]\fP" -.PP -Checks whether the watch is enabled. -.PP -\fBReturns:\fP -.RS 4 -true = enables, false = disabled -.RE -.PP - -.SS "bool InotifyWatch::IsRecursive () const\fC [inline]\fP" -.PP -Checks whether the watch is recursive. -.PP -A recursive watch monitors a directory itself and all its subdirectories. This watch is a logical object which may have many underlying kernel watches. -.PP -\fBReturns:\fP -.RS 4 -currently always false (recursive watches not yet supported) -.RE -.PP -\fBAttention:\fP -.RS 4 -Recursive watches are currently NOT supported. They are planned for future versions. -.RE -.PP - -.SS "void InotifyWatch::SetEnabled (bool fEnabled) throw (\fBInotifyException\fP)" -.PP -Enables/disables the watch. -.PP -If the watch is active (added to an instance of \fBInotify\fP) this method may fail due to unsuccessful re-setting the watch in the kernel. -.PP -Re-setting the current state has no effect. -.PP -\fBParameters:\fP -.RS 4 -\fIfEnabled\fP set enabled yes/no -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if enabling/disabling fails -.RE -.PP - -.SS "void InotifyWatch::SetMask (uint32_t uMask) throw (\fBInotifyException\fP)" -.PP -Sets the watch event mask. -.PP -If the watch is active (added to an instance of \fBInotify\fP) this method may fail due to unsuccessful re-setting the watch in the kernel. -.PP -\fBParameters:\fP -.RS 4 -\fIuMask\fP event mask -.RE -.PP -\fBExceptions:\fP -.RS 4 -\fI\fBInotifyException\fP\fP thrown if changing fails -.RE -.PP - -.SH "Friends And Related Function Documentation" -.PP -.SS "friend class \fBInotify\fP\fC [friend]\fP" -.PP -.SH "Member Data Documentation" -.PP -.SS "bool \fBInotifyWatch::m_fEnabled\fP\fC [private]\fP" -.PP -events enabled yes/no -.PP -.SS "std::string \fBInotifyWatch::m_path\fP\fC [private]\fP" -.PP -watched file path -.PP -.SS "\fBInotify\fP* \fBInotifyWatch::m_pInotify\fP\fC [private]\fP" -.PP -inotify object -.PP -.SS "uint32_t \fBInotifyWatch::m_uMask\fP\fC [private]\fP" -.PP -event mask -.PP -.SS "int32_t \fBInotifyWatch::m_wd\fP\fC [private]\fP" -.PP -watch descriptor -.PP - - -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/doc/man/man3/inotify-cxx.cpp.3 b/shared/inotify/doc/man/man3/inotify-cxx.cpp.3 deleted file mode 100644 index aed8e808..00000000 --- a/shared/inotify/doc/man/man3/inotify-cxx.cpp.3 +++ /dev/null @@ -1,80 +0,0 @@ -.TH "inotify-cxx.cpp" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -inotify-cxx.cpp \- inotify C++ interface implementation - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <errno.h>\fP -.br -\fC#include <unistd.h>\fP -.br -\fC#include <fcntl.h>\fP -.br -\fC#include <fstream>\fP -.br -\fC#include <sys/syscall.h>\fP -.br -\fC#include <sys/inotify-syscalls.h>\fP -.br -\fC#include 'inotify-cxx.h'\fP -.br - -.SS "Defines" - -.in +1c -.ti -1c -.RI "#define \fBPROCFS_INOTIFY_BASE\fP '/proc/sys/fs/inotify/'" -.br -.RI "\fIprocfs inotify base path \fP" -.ti -1c -.RI "#define \fBDUMP_SEP\fP" -.br -.RI "\fIdump separator (between particular entries) \fP" -.in -1c -.SH "Detailed Description" -.PP -inotify C++ interface implementation - -inotify C++ interface -.PP -Copyright (C) 2006, 2007, 2009 Lukas Jelinek <lukas@aiken.cz> -.PP -This program is free software; you can redistribute it and/or modify it under the terms of one of the following licenses: -.PP -.PD 0 -.IP "\(bu" 2 -1. X11-style license (see LICENSE-X11) -.IP "\(bu" 2 -2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) -.IP "\(bu" 2 -3. GNU General Public License, version 2 (see LICENSE-GPL) -.PP -If you want to help with choosing the best license for you, please visit http://www.gnu.org/licenses/license-list.html. -.PP -Credits: Mike Frysinger (cleanup of includes) -.SH "Define Documentation" -.PP -.SS "#define DUMP_SEP" -.PP -\fBValue:\fP -.PP -.nf -({ \ - if (!rStr.empty()) { \ - rStr.append(','); \ - } \ - }) -.fi -dump separator (between particular entries) -.PP -.SS "#define PROCFS_INOTIFY_BASE '/proc/sys/fs/inotify/'" -.PP -procfs inotify base path -.PP -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/doc/man/man3/inotify-cxx.h.3 b/shared/inotify/doc/man/man3/inotify-cxx.h.3 deleted file mode 100644 index 8c729b37..00000000 --- a/shared/inotify/doc/man/man3/inotify-cxx.h.3 +++ /dev/null @@ -1,198 +0,0 @@ -.TH "inotify-cxx.h" 3 "9 Dec 2009" "Version 0.7.3" "inotify-cxx" \" -*- nroff -*- -.ad l -.nh -.SH NAME -inotify-cxx.h \- inotify C++ interface header - -.PP -.SH SYNOPSIS -.br -.PP -\fC#include <stdint.h>\fP -.br -\fC#include <string>\fP -.br -\fC#include <deque>\fP -.br -\fC#include <map>\fP -.br -\fC#include <sys/inotify.h>\fP -.br - -.SS "Classes" - -.in +1c -.ti -1c -.RI "class \fBInotifyException\fP" -.br -.RI "\fIClass for inotify exceptions. \fP" -.ti -1c -.RI "class \fBInotifyEvent\fP" -.br -.RI "\fIinotify event class \fP" -.ti -1c -.RI "class \fBInotifyWatch\fP" -.br -.RI "\fIinotify watch class \fP" -.ti -1c -.RI "class \fBInotify\fP" -.br -.RI "\fIinotify class \fP" -.in -1c -.SS "Defines" - -.in +1c -.ti -1c -.RI "#define \fBINOTIFY_EVENT_SIZE\fP (sizeof(struct inotify_event))" -.br -.RI "\fIEvent struct size. \fP" -.ti -1c -.RI "#define \fBINOTIFY_BUFLEN\fP (1024 * (INOTIFY_EVENT_SIZE + 16))" -.br -.RI "\fIEvent buffer length. \fP" -.ti -1c -.RI "#define \fBIN_EXC_MSG\fP(msg) (std::string(__PRETTY_FUNCTION__) + ': ' + msg)" -.br -.RI "\fIHelper macro for creating exception messages. \fP" -.ti -1c -.RI "#define \fBIN_LOCK_DECL\fP" -.br -.RI "\fIinotify-cxx thread safety \fP" -.ti -1c -.RI "#define \fBIN_LOCK_INIT\fP" -.br -.ti -1c -.RI "#define \fBIN_LOCK_DONE\fP" -.br -.ti -1c -.RI "#define \fBIN_READ_BEGIN\fP" -.br -.ti -1c -.RI "#define \fBIN_READ_END\fP" -.br -.ti -1c -.RI "#define \fBIN_READ_END_NOTHROW\fP" -.br -.ti -1c -.RI "#define \fBIN_WRITE_BEGIN\fP" -.br -.ti -1c -.RI "#define \fBIN_WRITE_END\fP" -.br -.ti -1c -.RI "#define \fBIN_WRITE_END_NOTHROW\fP" -.br -.in -1c -.SS "Typedefs" - -.in +1c -.ti -1c -.RI "typedef std::map< int32_t, \fBInotifyWatch\fP * > \fBIN_WATCH_MAP\fP" -.br -.RI "\fIMapping from watch descriptors to watch objects. \fP" -.ti -1c -.RI "typedef std::map< std::string, \fBInotifyWatch\fP * > \fBIN_WP_MAP\fP" -.br -.RI "\fIMapping from paths to watch objects. \fP" -.in -1c -.SS "Enumerations" - -.in +1c -.ti -1c -.RI "enum \fBInotifyCapability_t\fP { \fBIN_MAX_EVENTS\fP = 0, \fBIN_MAX_INSTANCES\fP = 1, \fBIN_MAX_WATCHES\fP = 2 }" -.br -.RI "\fIinotify capability/limit identifiers \fP" -.in -1c -.SH "Detailed Description" -.PP -inotify C++ interface header - -inotify C++ interface -.PP -Copyright (C) 2006, 2007, 2009 Lukas Jelinek, <lukas@aiken.cz> -.PP -This program is free software; you can redistribute it and/or modify it under the terms of one of the following licenses: -.PP -.PD 0 -.IP "\(bu" 2 -1. X11-style license (see LICENSE-X11) -.IP "\(bu" 2 -2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) -.IP "\(bu" 2 -3. GNU General Public License, version 2 (see LICENSE-GPL) -.PP -If you want to help with choosing the best license for you, please visit http://www.gnu.org/licenses/license-list.html. -.PP -Credits: Mike Frysinger (cleanup of includes) -.SH "Define Documentation" -.PP -.SS "#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ': ' + msg)" -.PP -Helper macro for creating exception messages. -.PP -It prepends the message by the function name. -.SS "#define IN_LOCK_DECL" -.PP -inotify-cxx thread safety -.PP -If this symbol is defined you can use this interface safely threaded applications. Remember that it slightly degrades performance. -.PP -Even if INOTIFY_THREAD_SAFE is defined some classes stay unsafe. If you must use them (must you?) in more than one thread concurrently you need to implement explicite locking. -.PP -You need not to define INOTIFY_THREAD_SAFE in that cases where the application is multithreaded but all the inotify infrastructure will be managed only in one thread. This is the recommended way. -.PP -Locking may fail (it is very rare but not impossible). In this case an exception is thrown. But if unlocking fails in case of an error it does nothing (this failure is ignored). -.SS "#define IN_LOCK_DONE" -.PP -.SS "#define IN_LOCK_INIT" -.PP -.SS "#define IN_READ_BEGIN" -.PP -.SS "#define IN_READ_END" -.PP -.SS "#define IN_READ_END_NOTHROW" -.PP -.SS "#define IN_WRITE_BEGIN" -.PP -.SS "#define IN_WRITE_END" -.PP -.SS "#define IN_WRITE_END_NOTHROW" -.PP -.SS "#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))" -.PP -Event buffer length. -.PP -.SS "#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))" -.PP -Event struct size. -.PP -.SH "Typedef Documentation" -.PP -.SS "typedef std::map<int32_t, \fBInotifyWatch\fP*> \fBIN_WATCH_MAP\fP" -.PP -Mapping from watch descriptors to watch objects. -.PP -.SS "typedef std::map<std::string, \fBInotifyWatch\fP*> \fBIN_WP_MAP\fP" -.PP -Mapping from paths to watch objects. -.PP -.SH "Enumeration Type Documentation" -.PP -.SS "enum \fBInotifyCapability_t\fP" -.PP -inotify capability/limit identifiers -.PP -\fBEnumerator: \fP -.in +1c -.TP -\fB\fIIN_MAX_EVENTS \fP\fP -max. events in the kernel queue -.TP -\fB\fIIN_MAX_INSTANCES \fP\fP -max. inotify file descriptors per process -.TP -\fB\fIIN_MAX_WATCHES \fP\fP -max. watches per file descriptor -.SH "Author" -.PP -Generated automatically by Doxygen for inotify-cxx from the source code. diff --git a/shared/inotify/inotify-cxx.cpp b/shared/inotify/inotify-cxx.cpp deleted file mode 100644 index 5a460ec7..00000000 --- a/shared/inotify/inotify-cxx.cpp +++ /dev/null @@ -1,709 +0,0 @@ - -/// inotify C++ interface implementation -/** - * \file inotify-cxx.cpp - * - * inotify C++ interface - * - * Copyright (C) 2006, 2007, 2009 Lukas Jelinek <lukas@aiken.cz> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of one of the following licenses: - * - * \li 1. X11-style license (see LICENSE-X11) - * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) - * \li 3. GNU General Public License, version 2 (see LICENSE-GPL) - * - * If you want to help with choosing the best license for you, - * please visit http://www.gnu.org/licenses/license-list.html. - * - * Credits: - * Mike Frysinger (cleanup of includes) - * - */ - - -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <fstream> - -#include <sys/syscall.h> - -// Use this if syscalls not defined -#ifndef __NR_inotify_init -#include <sys/inotify-syscalls.h> -#endif // __NR_inotify_init - -#include "inotify-cxx.h" - -/// procfs inotify base path -#define PROCFS_INOTIFY_BASE "/proc/sys/fs/inotify/" - -/// dump separator (between particular entries) -#define DUMP_SEP \ - ({ \ - if (!rStr.empty()) { \ - rStr.append(","); \ - } \ - }) - - - -int32_t InotifyEvent::GetDescriptor() const -{ - return m_pWatch != NULL // if watch exists - ? m_pWatch->GetDescriptor() // return its descriptor - : -1; // else return -1 -} - -uint32_t InotifyEvent::GetMaskByName(const std::string& rName) -{ - if (rName == "IN_ACCESS") - return IN_ACCESS; - else if (rName == "IN_MODIFY") - return IN_MODIFY; - else if (rName == "IN_ATTRIB") - return IN_ATTRIB; - else if (rName == "IN_CLOSE_WRITE") - return IN_CLOSE_WRITE; - else if (rName == "IN_CLOSE_NOWRITE") - return IN_CLOSE_NOWRITE; - else if (rName == "IN_OPEN") - return IN_OPEN; - else if (rName == "IN_MOVED_FROM") - return IN_MOVED_FROM; - else if (rName == "IN_MOVED_TO") - return IN_MOVED_TO; - else if (rName == "IN_CREATE") - return IN_CREATE; - else if (rName == "IN_DELETE") - return IN_DELETE; - else if (rName == "IN_DELETE_SELF") - return IN_DELETE_SELF; - else if (rName == "IN_UNMOUNT") - return IN_UNMOUNT; - else if (rName == "IN_Q_OVERFLOW") - return IN_Q_OVERFLOW; - else if (rName == "IN_IGNORED") - return IN_IGNORED; - else if (rName == "IN_CLOSE") - return IN_CLOSE; - else if (rName == "IN_MOVE") - return IN_MOVE; - else if (rName == "IN_ISDIR") - return IN_ISDIR; - else if (rName == "IN_ONESHOT") - return IN_ONESHOT; - else if (rName == "IN_ALL_EVENTS") - return IN_ALL_EVENTS; - -#ifdef IN_DONT_FOLLOW - else if (rName == "IN_DONT_FOLLOW") - return IN_DONT_FOLLOW; -#endif // IN_DONT_FOLLOW - -#ifdef IN_ONLYDIR - else if (rName == "IN_ONLYDIR") - return IN_ONLYDIR; -#endif // IN_ONLYDIR - -#ifdef IN_MOVE_SELF - else if (rName == "IN_MOVE_SELF") - return IN_MOVE_SELF; -#endif // IN_MOVE_SELF - - return (uint32_t) 0; -} - -void InotifyEvent::DumpTypes(uint32_t uValue, std::string& rStr) -{ - rStr = ""; - - if (IsType(uValue, IN_ALL_EVENTS)) - { - rStr.append("IN_ALL_EVENTS"); - } - else - { - if (IsType(uValue, IN_ACCESS)) - { - DUMP_SEP; - rStr.append("IN_ACCESS"); - } - if (IsType(uValue, IN_MODIFY)) - { - DUMP_SEP; - rStr.append("IN_MODIFY"); - } - if (IsType(uValue, IN_ATTRIB)) - { - DUMP_SEP; - rStr.append("IN_ATTRIB"); - } - if (IsType(uValue, IN_CREATE)) - { - DUMP_SEP; - rStr.append("IN_CREATE"); - } - if (IsType(uValue, IN_DELETE)) - { - DUMP_SEP; - rStr.append("IN_DELETE"); - } - if (IsType(uValue, IN_DELETE_SELF)) - { - DUMP_SEP; - rStr.append("IN_DELETE_SELF"); - } - if (IsType(uValue, IN_OPEN)) - { - DUMP_SEP; - rStr.append("IN_OPEN"); - } - if (IsType(uValue, IN_CLOSE)) - { - DUMP_SEP; - rStr.append("IN_CLOSE"); - } - -#ifdef IN_MOVE_SELF - if (IsType(uValue, IN_MOVE_SELF)) - { - DUMP_SEP; - rStr.append("IN_MOVE_SELF"); - } -#endif // IN_MOVE_SELF - - else - { - if (IsType(uValue, IN_CLOSE_WRITE)) - { - DUMP_SEP; - rStr.append("IN_CLOSE_WRITE"); - } - if (IsType(uValue, IN_CLOSE_NOWRITE)) - { - DUMP_SEP; - rStr.append("IN_CLOSE_NOWRITE"); - } - } - if (IsType(uValue, IN_MOVE)) - { - DUMP_SEP; - rStr.append("IN_MOVE"); - } - else - { - if (IsType(uValue, IN_MOVED_FROM)) - { - DUMP_SEP; - rStr.append("IN_MOVED_FROM"); - } - if (IsType(uValue, IN_MOVED_TO)) - { - DUMP_SEP; - rStr.append("IN_MOVED_TO"); - } - } - } - if (IsType(uValue, IN_UNMOUNT)) - { - DUMP_SEP; - rStr.append("IN_UNMOUNT"); - } - if (IsType(uValue, IN_Q_OVERFLOW)) - { - DUMP_SEP; - rStr.append("IN_Q_OVERFLOW"); - } - if (IsType(uValue, IN_IGNORED)) - { - DUMP_SEP; - rStr.append("IN_IGNORED"); - } - if (IsType(uValue, IN_ISDIR)) - { - DUMP_SEP; - rStr.append("IN_ISDIR"); - } - if (IsType(uValue, IN_ONESHOT)) - { - DUMP_SEP; - rStr.append("IN_ONESHOT"); - } - -#ifdef IN_DONT_FOLLOW - if (IsType(uValue, IN_DONT_FOLLOW)) - { - DUMP_SEP; - rStr.append("IN_DONT_FOLLOW"); - } -#endif // IN_DONT_FOLLOW - -#ifdef IN_ONLYDIR - if (IsType(uValue, IN_ONLYDIR)) - { - DUMP_SEP; - rStr.append("IN_ONLYDIR"); - } -#endif // IN_ONLYDIR -} - -void InotifyEvent::DumpTypes(std::string& rStr) const -{ - DumpTypes(m_uMask, rStr); -} - - -void InotifyWatch::SetMask(uint32_t uMask) throw (InotifyException) -{ - IN_WRITE_BEGIN - - if (m_wd != -1) - { - int wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), uMask); - if (wd != m_wd) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("changing mask failed"), wd == -1 ? errno : EINVAL, this); - } - } - - m_uMask = uMask; - - IN_WRITE_END -} - -void InotifyWatch::SetEnabled(bool fEnabled) throw (InotifyException) -{ - IN_WRITE_BEGIN - - if (fEnabled == m_fEnabled) - { - IN_WRITE_END_NOTHROW - return; - } - - if (m_pInotify != NULL) - { - if (fEnabled) - { - m_wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), m_uMask); - if (m_wd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("enabling watch failed"), errno, this); - } - m_pInotify->m_watches.insert(IN_WATCH_MAP::value_type(m_wd, this)); - } - else - { - if (inotify_rm_watch(m_pInotify->GetDescriptor(), m_wd) != 0) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("disabling watch failed"), errno, this); - } - m_pInotify->m_watches.erase(m_wd); - m_wd = -1; - } - } - - m_fEnabled = fEnabled; - - IN_WRITE_END -} - -void InotifyWatch::__Disable() -{ - IN_WRITE_BEGIN - - if (!m_fEnabled) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("event cannot occur on disabled watch"), EINVAL, this); - } - - if (m_pInotify != NULL) - { - m_pInotify->m_watches.erase(m_wd); - m_wd = -1; - } - - m_fEnabled = false; - - IN_WRITE_END -} - - -Inotify::Inotify() throw (InotifyException) -{ - IN_LOCK_INIT - - m_fd = inotify_init(); - if (m_fd == -1) - { - IN_LOCK_DONE - throw InotifyException(IN_EXC_MSG("inotify init failed"), errno, NULL); - } -} - -Inotify::~Inotify() -{ - Close(); - - IN_LOCK_DONE -} - -void Inotify::Close() -{ - IN_WRITE_BEGIN - - if (m_fd != -1) - { - RemoveAll(); - close(m_fd); - m_fd = -1; - } - - IN_WRITE_END -} - -void Inotify::Add(InotifyWatch* pWatch) throw (InotifyException) -{ - IN_WRITE_BEGIN - - // invalid descriptor - this case shouldn't occur - go away - if (m_fd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); - } - - // this path already watched - go away - if (FindWatch(pWatch->GetPath()) != NULL) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("path already watched"), EBUSY, this); - } - - // for enabled watch - if (pWatch->IsEnabled()) - { - - // try to add watch to kernel - int wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask()); - - // adding failed - go away - if (wd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this); - } - - // this path already watched (but defined another way) - InotifyWatch* pW = FindWatch(wd); - if (pW != NULL) - { - - // try to recover old watch because it may be modified - then go away - if (inotify_add_watch(m_fd, pW->GetPath().c_str(), pW->GetMask()) < 0) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("watch collision detected and recovery failed"), errno, this); - } - else - { - // recovery failed - go away - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("path already watched (but defined another way)"), EBUSY, this); - } - } - - pWatch->m_wd = wd; - m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch)); - } - - m_paths.insert(IN_WP_MAP::value_type(pWatch->m_path, pWatch)); - pWatch->m_pInotify = this; - - IN_WRITE_END -} - -void Inotify::Remove(InotifyWatch* pWatch) throw (InotifyException) -{ - IN_WRITE_BEGIN - - // invalid descriptor - this case shouldn't occur - go away - if (m_fd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); - } - - // for enabled watch - if (pWatch->m_wd != -1) - { - - // removing watch failed - go away - if (inotify_rm_watch(m_fd, pWatch->m_wd) == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this); - } - m_watches.erase(pWatch->m_wd); - pWatch->m_wd = -1; - } - - m_paths.erase(pWatch->m_path); - pWatch->m_pInotify = NULL; - - IN_WRITE_END -} - -void Inotify::RemoveAll() -{ - IN_WRITE_BEGIN - - IN_WP_MAP::iterator it = m_paths.begin(); - while (it != m_paths.end()) - { - InotifyWatch* pW = (*it).second; - if (pW->m_wd != -1) - { - inotify_rm_watch(m_fd, pW->m_wd); - pW->m_wd = -1; - } - pW->m_pInotify = NULL; - it++; - } - - m_watches.clear(); - m_paths.clear(); - - IN_WRITE_END -} - -void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException) -{ - ssize_t len = 0; - - do - { - len = read(m_fd, m_buf, INOTIFY_BUFLEN); - } - while (fNoIntr && len == -1 && errno == EINTR); - - if (len == -1 && !(errno == EWOULDBLOCK || errno == EINTR)) - throw InotifyException(IN_EXC_MSG("reading events failed"), errno, this); - - if (len == -1) - return; - - IN_WRITE_BEGIN - - ssize_t i = 0; - while (i < len) - { - struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i]; - InotifyWatch* pW = FindWatch(pEvt->wd); - if (pW != NULL) - { - InotifyEvent evt(pEvt, pW); - if ( InotifyEvent::IsType(pW->GetMask(), IN_ONESHOT) - || InotifyEvent::IsType(evt.GetMask(), IN_IGNORED)) - pW->__Disable(); - m_events.push_back(evt); - } - i += INOTIFY_EVENT_SIZE + (ssize_t) pEvt->len; - } - - IN_WRITE_END -} - -bool Inotify::GetEvent(InotifyEvent* pEvt) throw (InotifyException) -{ - if (pEvt == NULL) - throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); - - IN_WRITE_BEGIN - - bool b = !m_events.empty(); - if (b) - { - *pEvt = m_events.front(); - m_events.pop_front(); - } - - IN_WRITE_END - - return b; -} - -bool Inotify::PeekEvent(InotifyEvent* pEvt) throw (InotifyException) -{ - if (pEvt == NULL) - throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); - - IN_READ_BEGIN - - bool b = !m_events.empty(); - if (b) - { - *pEvt = m_events.front(); - } - - IN_READ_END - - return b; -} - -InotifyWatch* Inotify::FindWatch(int iDescriptor) -{ - IN_READ_BEGIN - - IN_WATCH_MAP::iterator it = m_watches.find(iDescriptor); - InotifyWatch* pW = it == m_watches.end() ? NULL : (*it).second; - - IN_READ_END - - return pW; -} - -InotifyWatch* Inotify::FindWatch(const std::string& rPath) -{ - IN_READ_BEGIN - - IN_WP_MAP::iterator it = m_paths.find(rPath); - InotifyWatch* pW = it == m_paths.end() ? NULL : (*it).second; - - IN_READ_END - - return pW; -} - -void Inotify::SetNonBlock(bool fNonBlock) throw (InotifyException) -{ - IN_WRITE_BEGIN - - if (m_fd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); - } - - int res = fcntl(m_fd, F_GETFL); - if (res == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); - } - - if (fNonBlock) - { - res |= O_NONBLOCK; - } - else - { - res &= ~O_NONBLOCK; - } - - if (fcntl(m_fd, F_SETFL, res) == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); - } - - IN_WRITE_END -} - -void Inotify::SetCloseOnExec(bool fClOnEx) throw (InotifyException) -{ - IN_WRITE_BEGIN - - if (m_fd == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); - } - - int res = fcntl(m_fd, F_GETFD); - if (res == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); - } - - if (fClOnEx) - { - res |= FD_CLOEXEC; - } - else - { - res &= ~FD_CLOEXEC; - } - - if (fcntl(m_fd, F_SETFD, res) == -1) - { - IN_WRITE_END_NOTHROW - throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); - } - - IN_WRITE_END -} - -uint32_t Inotify::GetCapability(InotifyCapability_t cap) throw (InotifyException) -{ - FILE* f = fopen(GetCapabilityPath(cap).c_str(), "r"); - if (f == NULL) - throw InotifyException(IN_EXC_MSG("cannot get capability"), errno, NULL); - - unsigned int val = 0; - if (fscanf(f, "%u", &val) != 1) - { - fclose(f); - throw InotifyException(IN_EXC_MSG("cannot get capability"), EIO, NULL); - } - - fclose(f); - - return (uint32_t) val; -} - -void Inotify::SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException) -{ - FILE* f = fopen(GetCapabilityPath(cap).c_str(), "w"); - if (f == NULL) - throw InotifyException(IN_EXC_MSG("cannot set capability"), errno, NULL); - - if (fprintf(f, "%u", (unsigned int) val) <= 0) - { - fclose(f); - throw InotifyException(IN_EXC_MSG("cannot set capability"), EIO, NULL); - } - - fclose(f); -} - -std::string Inotify::GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException) -{ - std::string path(PROCFS_INOTIFY_BASE); - - switch (cap) - { - case IN_MAX_EVENTS: - path.append("max_queued_events"); - break; - case IN_MAX_INSTANCES: - path.append("max_user_instances"); - break; - case IN_MAX_WATCHES: - path.append("max_user_watches"); - break; - default: - throw InotifyException(IN_EXC_MSG("unknown capability type"), EINVAL, NULL); - } - - return path; -} - diff --git a/shared/inotify/inotify-cxx.h b/shared/inotify/inotify-cxx.h deleted file mode 100644 index 2fb00fc8..00000000 --- a/shared/inotify/inotify-cxx.h +++ /dev/null @@ -1,890 +0,0 @@ - -/// inotify C++ interface header -/** - * \file inotify-cxx.h - * - * inotify C++ interface - * - * Copyright (C) 2006, 2007, 2009 Lukas Jelinek, <lukas@aiken.cz> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of one of the following licenses: - * - * \li 1. X11-style license (see LICENSE-X11) - * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL) - * \li 3. GNU General Public License, version 2 (see LICENSE-GPL) - * - * If you want to help with choosing the best license for you, - * please visit http://www.gnu.org/licenses/license-list.html. - * - * Credits: - * Mike Frysinger (cleanup of includes) - * - */ - - - - - -#ifndef _INOTIFYCXX_H_ -#define _INOTIFYCXX_H_ - -#include <stdint.h> -#include <string> -#include <deque> -#include <map> - -// Please ensure that the following header file takes the right place -#include <sys/inotify.h> - - -/// Event struct size -#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) - -/// Event buffer length -#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16)) - -/// Helper macro for creating exception messages. -/** - * It prepends the message by the function name. - */ -#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg) - -/// inotify capability/limit identifiers -typedef enum -{ - IN_MAX_EVENTS = 0, ///< max. events in the kernel queue - IN_MAX_INSTANCES = 1, ///< max. inotify file descriptors per process - IN_MAX_WATCHES = 2 ///< max. watches per file descriptor -} InotifyCapability_t; - -/// inotify-cxx thread safety -/** - * If this symbol is defined you can use this interface safely - * threaded applications. Remember that it slightly degrades - * performance. - * - * Even if INOTIFY_THREAD_SAFE is defined some classes stay - * unsafe. If you must use them (must you?) in more than one - * thread concurrently you need to implement explicite locking. - * - * You need not to define INOTIFY_THREAD_SAFE in that cases - * where the application is multithreaded but all the inotify - * infrastructure will be managed only in one thread. This is - * the recommended way. - * - * Locking may fail (it is very rare but not impossible). In this - * case an exception is thrown. But if unlocking fails in case - * of an error it does nothing (this failure is ignored). - */ -#ifdef INOTIFY_THREAD_SAFE - -#include <pthread.h> - -#define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock; - -#define IN_LOCK_INIT \ - { \ - pthread_rwlockattr_t attr; \ - int res = 0; \ - if ((res = pthread_rwlockattr_init(&attr)) != 0) \ - throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \ - if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \ - throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \ - if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \ - throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \ - pthread_rwlockattr_destroy(&attr); \ - } - -#define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock); - -#define IN_READ_BEGIN \ - { \ - int res = pthread_rwlock_rdlock(&__m_lock); \ - if (res != 0) \ - throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \ - } - -#define IN_READ_END \ - { \ - int res = pthread_rwlock_unlock(&__m_lock); \ - if (res != 0) \ - throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \ - } - -#define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock); - -#define IN_WRITE_BEGIN \ - { \ - int res = pthread_rwlock_wrlock(&__m_lock); \ - if (res != 0) \ - throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \ - } - -#define IN_WRITE_END IN_READ_END -#define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW - -#else // INOTIFY_THREAD_SAFE - -#define IN_LOCK_DECL -#define IN_LOCK_INIT -#define IN_LOCK_DONE -#define IN_READ_BEGIN -#define IN_READ_END -#define IN_READ_END_NOTHROW -#define IN_WRITE_BEGIN -#define IN_WRITE_END -#define IN_WRITE_END_NOTHROW - -#endif // INOTIFY_THREAD_SAFE - - - - -// forward declaration -class InotifyWatch; -class Inotify; - - -/// Class for inotify exceptions -/** - * This class allows to acquire information about exceptional - * events. It makes easier to log or display error messages - * and to identify problematic code locations. - * - * Although this class is basically thread-safe it is not intended - * to be shared between threads. - */ -class InotifyException -{ -public: - /// Constructor - /** - * \param[in] rMsg message - * \param[in] iErr error number (see errno.h) - * \param[in] pSrc source - */ - InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL) - : m_msg(rMsg), - m_err(iErr) - { - m_pSrc = pSrc; - } - - /// Returns the exception message. - /** - * \return message - */ - inline const std::string& GetMessage() const - { - return m_msg; - } - - /// Returns the exception error number. - /** - * If not applicable this value is 0 (zero). - * - * \return error number (standardized; see errno.h) - */ - inline int GetErrorNumber() const - { - return m_err; - } - - /// Returns the exception source. - /** - * \return source - */ - inline void* GetSource() const - { - return m_pSrc; - } - -protected: - std::string m_msg; ///< message - int m_err; ///< error number - mutable void* m_pSrc; ///< source -}; - - -/// inotify event class -/** - * It holds all information about inotify event and provides - * access to its particular values. - * - * This class is not (and is not intended to be) thread-safe - * and therefore it must not be used concurrently in multiple - * threads. - */ -class InotifyEvent -{ -public: - /// Constructor. - /** - * Creates a plain event. - */ - InotifyEvent() - : m_uMask(0), - m_uCookie(0) - { - m_pWatch = NULL; - } - - /// Constructor. - /** - * Creates an event based on inotify event data. - * For NULL pointers it works the same way as InotifyEvent(). - * - * \param[in] pEvt event data - * \param[in] pWatch inotify watch - */ - InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch) - : m_uMask(0), - m_uCookie(0) - { - if (pEvt != NULL) - { - m_uMask = (uint32_t) pEvt->mask; - m_uCookie = (uint32_t) pEvt->cookie; - if (pEvt->name != NULL) - { - m_name = pEvt->len > 0 - ? pEvt->name - : ""; - } - m_pWatch = pWatch; - } - else - { - m_pWatch = NULL; - } - } - - /// Destructor. - ~InotifyEvent() {} - - /// Returns the event watch descriptor. - /** - * \return watch descriptor - * - * \sa InotifyWatch::GetDescriptor() - */ - int32_t GetDescriptor() const; - - /// Returns the event mask. - /** - * \return event mask - * - * \sa InotifyWatch::GetMask() - */ - inline uint32_t GetMask() const - { - return m_uMask; - } - - /// Checks a value for the event type. - /** - * \param[in] uValue checked value - * \param[in] uType type which is checked for - * \return true = the value contains the given type, false = otherwise - */ - inline static bool IsType(uint32_t uValue, uint32_t uType) - { - return ((uValue & uType) != 0) && ((~uValue & uType) == 0); - } - - /// Checks for the event type. - /** - * \param[in] uType type which is checked for - * \return true = event mask contains the given type, false = otherwise - */ - inline bool IsType(uint32_t uType) const - { - return IsType(m_uMask, uType); - } - - /// Returns the event cookie. - /** - * \return event cookie - */ - inline uint32_t GetCookie() const - { - return m_uCookie; - } - - /// Returns the event name length. - /** - * \return event name length - */ - inline uint32_t GetLength() const - { - return (uint32_t) m_name.length(); - } - - /// Returns the event name. - /** - * \return event name - */ - inline const std::string& GetName() const - { - return m_name; - } - - /// Extracts the event name. - /** - * \param[out] rName event name - */ - inline void GetName(std::string& rName) const - { - rName = GetName(); - } - - /// Returns the source watch. - /** - * \return source watch - */ - inline InotifyWatch* GetWatch() - { - return m_pWatch; - } - - /// Finds the appropriate mask for a name. - /** - * \param[in] rName mask name - * \return mask for name; 0 on failure - */ - static uint32_t GetMaskByName(const std::string& rName); - - /// Fills the string with all types contained in an event mask value. - /** - * \param[in] uValue event mask value - * \param[out] rStr dumped event types - */ - static void DumpTypes(uint32_t uValue, std::string& rStr); - - /// Fills the string with all types contained in the event mask. - /** - * \param[out] rStr dumped event types - */ - void DumpTypes(std::string& rStr) const; - -private: - uint32_t m_uMask; ///< mask - uint32_t m_uCookie; ///< cookie - std::string m_name; ///< name - InotifyWatch* m_pWatch; ///< source watch -}; - - - -/// inotify watch class -/** - * It holds information about the inotify watch on a particular - * inode. - * - * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. - */ -class InotifyWatch -{ -public: - /// Constructor. - /** - * Creates an inotify watch. Because this watch is - * inactive it has an invalid descriptor (-1). - * - * \param[in] rPath watched file path - * \param[in] uMask mask for events - * \param[in] fEnabled events enabled yes/no - */ - InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true) - : m_path(rPath), - m_uMask(uMask), - m_wd((int32_t) -1), - m_fEnabled(fEnabled) - { - IN_LOCK_INIT - } - - /// Destructor. - ~InotifyWatch() - { - IN_LOCK_DONE - } - - /// Returns the watch descriptor. - /** - * \return watch descriptor; -1 for inactive watch - */ - inline int32_t GetDescriptor() const - { - return m_wd; - } - - /// Returns the watched file path. - /** - * \return file path - */ - inline const std::string& GetPath() const - { - return m_path; - } - - /// Returns the watch event mask. - /** - * \return event mask - */ - inline uint32_t GetMask() const - { - return (uint32_t) m_uMask; - } - - /// Sets the watch event mask. - /** - * If the watch is active (added to an instance of Inotify) - * this method may fail due to unsuccessful re-setting - * the watch in the kernel. - * - * \param[in] uMask event mask - * - * \throw InotifyException thrown if changing fails - */ - void SetMask(uint32_t uMask) throw (InotifyException); - - /// Returns the appropriate inotify class instance. - /** - * \return inotify instance - */ - inline Inotify* GetInotify() - { - return m_pInotify; - } - - /// Enables/disables the watch. - /** - * If the watch is active (added to an instance of Inotify) - * this method may fail due to unsuccessful re-setting - * the watch in the kernel. - * - * Re-setting the current state has no effect. - * - * \param[in] fEnabled set enabled yes/no - * - * \throw InotifyException thrown if enabling/disabling fails - */ - void SetEnabled(bool fEnabled) throw (InotifyException); - - /// Checks whether the watch is enabled. - /** - * \return true = enables, false = disabled - */ - inline bool IsEnabled() const - { - return m_fEnabled; - } - - /// Checks whether the watch is recursive. - /** - * A recursive watch monitors a directory itself and all - * its subdirectories. This watch is a logical object - * which may have many underlying kernel watches. - * - * \return currently always false (recursive watches not yet supported) - * \attention Recursive watches are currently NOT supported. - * They are planned for future versions. - */ - inline bool IsRecursive() const - { - return false; - } - -private: - friend class Inotify; - - std::string m_path; ///< watched file path - uint32_t m_uMask; ///< event mask - int32_t m_wd; ///< watch descriptor - Inotify* m_pInotify; ///< inotify object - bool m_fEnabled; ///< events enabled yes/no - - IN_LOCK_DECL - - /// Disables the watch (due to removing by the kernel). - /** - * This method must be called after receiving an event. - * It ensures the watch object is consistent with the kernel - * data. - */ - void __Disable(); -}; - - -/// Mapping from watch descriptors to watch objects. -typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP; - -/// Mapping from paths to watch objects. -typedef std::map<std::string, InotifyWatch*> IN_WP_MAP; - - -/// inotify class -/** - * It holds information about the inotify device descriptor - * and manages the event queue. - * - * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe. - */ -class Inotify -{ -public: - /// Constructor. - /** - * Creates and initializes an instance of inotify communication - * object (opens the inotify device). - * - * \throw InotifyException thrown if inotify isn't available - */ - Inotify() throw (InotifyException); - - /// Destructor. - /** - * Calls Close() due to clean-up. - */ - ~Inotify(); - - /// Removes all watches and closes the inotify device. - void Close(); - - /// Adds a new watch. - /** - * \param[in] pWatch inotify watch - * - * \throw InotifyException thrown if adding failed - */ - void Add(InotifyWatch* pWatch) throw (InotifyException); - - /// Adds a new watch. - /** - * \param[in] rWatch inotify watch - * - * \throw InotifyException thrown if adding failed - */ - inline void Add(InotifyWatch& rWatch) throw (InotifyException) - { - Add(&rWatch); - } - - /// Removes a watch. - /** - * If the given watch is not present it does nothing. - * - * \param[in] pWatch inotify watch - * - * \throw InotifyException thrown if removing failed - */ - void Remove(InotifyWatch* pWatch) throw (InotifyException); - - /// Removes a watch. - /** - * If the given watch is not present it does nothing. - * - * \param[in] rWatch inotify watch - * - * \throw InotifyException thrown if removing failed - */ - inline void Remove(InotifyWatch& rWatch) throw (InotifyException) - { - Remove(&rWatch); - } - - /// Removes all watches. - void RemoveAll(); - - /// Returns the count of watches. - /** - * This is the total count of all watches (regardless whether - * enabled or not). - * - * \return count of watches - * - * \sa GetEnabledCount() - */ - inline size_t GetWatchCount() const - { - IN_READ_BEGIN - size_t n = (size_t) m_paths.size(); - IN_READ_END - return n; - } - - /// Returns the count of enabled watches. - /** - * \return count of enabled watches - * - * \sa GetWatchCount() - */ - inline size_t GetEnabledCount() const - { - IN_READ_BEGIN - size_t n = (size_t) m_watches.size(); - IN_READ_END - return n; - } - - /// Waits for inotify events. - /** - * It waits until one or more events occur. When called - * in nonblocking mode it only retrieves occurred events - * to the internal queue and exits. - * - * \param[in] fNoIntr if true it re-calls the system call after a handled signal - * - * \throw InotifyException thrown if reading events failed - * - * \sa SetNonBlock() - */ - void WaitForEvents(bool fNoIntr = false) throw (InotifyException); - - /// Returns the count of received and queued events. - /** - * This number is related to the events in the queue inside - * this object, not to the events pending in the kernel. - * - * \return count of events - */ - inline size_t GetEventCount() - { - IN_READ_BEGIN - size_t n = (size_t) m_events.size(); - IN_READ_END - return n; - } - - /// Extracts a queued inotify event. - /** - * The extracted event is removed from the queue. - * If the pointer is NULL it does nothing. - * - * \param[in,out] pEvt event object - * - * \throw InotifyException thrown if the provided pointer is NULL - */ - bool GetEvent(InotifyEvent* pEvt) throw (InotifyException); - - /// Extracts a queued inotify event. - /** - * The extracted event is removed from the queue. - * - * \param[in,out] rEvt event object - * - * \throw InotifyException thrown only in very anomalous cases - */ - bool GetEvent(InotifyEvent& rEvt) throw (InotifyException) - { - return GetEvent(&rEvt); - } - - /// Extracts a queued inotify event (without removing). - /** - * The extracted event stays in the queue. - * If the pointer is NULL it does nothing. - * - * \param[in,out] pEvt event object - * - * \throw InotifyException thrown if the provided pointer is NULL - */ - bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException); - - /// Extracts a queued inotify event (without removing). - /** - * The extracted event stays in the queue. - * - * \param[in,out] rEvt event object - * - * \throw InotifyException thrown only in very anomalous cases - */ - bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException) - { - return PeekEvent(&rEvt); - } - - /// Searches for a watch by a watch descriptor. - /** - * It tries to find a watch by the given descriptor. - * - * \param[in] iDescriptor watch descriptor - * \return pointer to a watch; NULL if no such watch exists - */ - InotifyWatch* FindWatch(int iDescriptor); - - /// Searches for a watch by a filesystem path. - /** - * It tries to find a watch by the given filesystem path. - * - * \param[in] rPath filesystem path - * \return pointer to a watch; NULL if no such watch exists - * - * \attention The path must be exactly identical to the one - * used for the searched watch. Be careful about - * absolute/relative and case-insensitive paths. - */ - InotifyWatch* FindWatch(const std::string& rPath); - - /// Returns the file descriptor. - /** - * The descriptor can be used in standard low-level file - * functions (poll(), select(), fcntl() etc.). - * - * \return valid file descriptor or -1 for inactive object - * - * \sa SetNonBlock() - */ - inline int GetDescriptor() const - { - return m_fd; - } - - /// Enables/disables non-blocking mode. - /** - * Use this mode if you want to monitor the descriptor - * (acquired thru GetDescriptor()) in functions such as - * poll(), select() etc. - * - * Non-blocking mode is disabled by default. - * - * \param[in] fNonBlock enable/disable non-blocking mode - * - * \throw InotifyException thrown if setting mode failed - * - * \sa GetDescriptor(), SetCloseOnExec() - */ - void SetNonBlock(bool fNonBlock) throw (InotifyException); - - /// Enables/disables closing on exec. - /** - * Enable this if you want to close the descriptor when - * executing another program. Otherwise, the descriptor - * will be inherited. - * - * Closing on exec is disabled by default. - * - * \param[in] fClOnEx enable/disable closing on exec - * - * \throw InotifyException thrown if setting failed - * - * \sa GetDescriptor(), SetNonBlock() - */ - void SetCloseOnExec(bool fClOnEx) throw (InotifyException); - - /// Acquires a particular inotify capability/limit. - /** - * \param[in] cap capability/limit identifier - * \return capability/limit value - * \throw InotifyException thrown if the given value cannot be acquired - */ - static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException); - - /// Modifies a particular inotify capability/limit. - /** - * \param[in] cap capability/limit identifier - * \param[in] val new capability/limit value - * \throw InotifyException thrown if the given value cannot be set - * \attention Using this function requires root privileges. - * Beware of setting extensive values - it may seriously - * affect system performance and/or stability. - */ - static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException); - - /// Returns the maximum number of events in the kernel queue. - /** - * \return maximum number of events in the kernel queue - * \throw InotifyException thrown if the given value cannot be acquired - */ - inline static uint32_t GetMaxEvents() throw (InotifyException) - { - return GetCapability(IN_MAX_EVENTS); - } - - /// Sets the maximum number of events in the kernel queue. - /** - * \param[in] val new value - * \throw InotifyException thrown if the given value cannot be set - * \attention Using this function requires root privileges. - * Beware of setting extensive values - the greater value - * is set here the more physical memory may be used for the inotify - * infrastructure. - */ - inline static void SetMaxEvents(uint32_t val) throw (InotifyException) - { - SetCapability(IN_MAX_EVENTS, val); - } - - /// Returns the maximum number of inotify instances per process. - /** - * It means the maximum number of open inotify file descriptors - * per running process. - * - * \return maximum number of inotify instances - * \throw InotifyException thrown if the given value cannot be acquired - */ - inline static uint32_t GetMaxInstances() throw (InotifyException) - { - return GetCapability(IN_MAX_INSTANCES); - } - - /// Sets the maximum number of inotify instances per process. - /** - * \param[in] val new value - * \throw InotifyException thrown if the given value cannot be set - * \attention Using this function requires root privileges. - * Beware of setting extensive values - the greater value - * is set here the more physical memory may be used for the inotify - * infrastructure. - */ - inline static void SetMaxInstances(uint32_t val) throw (InotifyException) - { - SetCapability(IN_MAX_INSTANCES, val); - } - - /// Returns the maximum number of inotify watches per instance. - /** - * It means the maximum number of inotify watches per inotify - * file descriptor. - * - * \return maximum number of inotify watches - * \throw InotifyException thrown if the given value cannot be acquired - */ - inline static uint32_t GetMaxWatches() throw (InotifyException) - { - return GetCapability(IN_MAX_WATCHES); - } - - /// Sets the maximum number of inotify watches per instance. - /** - * \param[in] val new value - * \throw InotifyException thrown if the given value cannot be set - * \attention Using this function requires root privileges. - * Beware of setting extensive values - the greater value - * is set here the more physical memory may be used for the inotify - * infrastructure. - */ - inline static void SetMaxWatches(uint32_t val) throw (InotifyException) - { - SetCapability(IN_MAX_WATCHES, val); - } - -private: - int m_fd; ///< file descriptor - IN_WATCH_MAP m_watches; ///< watches (by descriptors) - IN_WP_MAP m_paths; ///< watches (by paths) - unsigned char m_buf[INOTIFY_BUFLEN]; ///< buffer for events - std::deque<InotifyEvent> m_events; ///< event queue - - IN_LOCK_DECL - - friend class InotifyWatch; - - static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException); -}; - - -#endif //_INOTIFYCXX_H_ - diff --git a/shared/last_error.cpp b/shared/last_error.cpp index 8109b669..ea8345bc 100644 --- a/shared/last_error.cpp +++ b/shared/last_error.cpp @@ -5,7 +5,7 @@ // ************************************************************************** // #include "last_error.h" -#include "string_tools.h" +#include "string_utf8.h" #include "i18n.h" #ifdef FFS_WIN @@ -16,17 +16,18 @@ #include <cerrno> #endif +using namespace zen; #ifdef FFS_WIN -wxString zen::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information +std::wstring zen::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information { //determine error code if none was specified if (lastError == 0) lastError = ::GetLastError(); - wxString output = _("Windows Error Code %x:"); - output.Replace(wxT("%x"), zen::toString<wxString>(lastError)); + std::wstring output = _("Windows Error Code %x:"); + replace(output, L"%x", toString<std::wstring>(lastError)); LPWSTR buffer = NULL; if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | @@ -36,7 +37,7 @@ wxString zen::getLastErrorFormatted(unsigned long lastError) //try to get additi { if (buffer) //just to be sure { - output += wxT(" "); + output += L" "; output += buffer; ::LocalFree(buffer); } @@ -46,16 +47,17 @@ wxString zen::getLastErrorFormatted(unsigned long lastError) //try to get additi } #elif defined FFS_LINUX -wxString zen::getLastErrorFormatted(int lastError) //try to get additional Linux error information +std::wstring zen::getLastErrorFormatted(int lastError) //try to get additional Linux error information { //determine error code if none was specified if (lastError == 0) lastError = errno; //don't use "::", errno is a macro! - wxString output = _("Linux Error Code %x:"); - output.Replace(wxT("%x"), zen::toString<wxString>(lastError)); + std::wstring output = _("Linux Error Code %x:"); + replace(output, L"%x", toString<std::wstring>(lastError)); - output += wxT(" ") + wxString::FromUTF8(::strerror(lastError)); + output += L" "; + output += utf8CvrtTo<std::wstring>(::strerror(lastError)); errno = lastError; //restore errno return output; diff --git a/shared/last_error.h b/shared/last_error.h index 9db41222..b617ebf5 100644 --- a/shared/last_error.h +++ b/shared/last_error.h @@ -7,16 +7,16 @@ #ifndef SYSTEMFUNCTIONS_H_INCLUDED #define SYSTEMFUNCTIONS_H_INCLUDED -#include <wx/string.h> +#include <string> namespace zen { //evaluate GetLastError()/errno and assemble specific error message #ifdef FFS_WIN -wxString getLastErrorFormatted(unsigned long lastError = 0); +std::wstring getLastErrorFormatted(unsigned long lastError = 0); #elif defined FFS_LINUX -wxString getLastErrorFormatted(int lastError = 0); +std::wstring getLastErrorFormatted(int lastError = 0); #endif } diff --git a/shared/localization.cpp b/shared/localization.cpp index 36773fc3..919009d6 100644 --- a/shared/localization.cpp +++ b/shared/localization.cpp @@ -12,14 +12,14 @@ #include <wx/ffile.h> #include <wx/intl.h> #include <wx/msgdlg.h> -#include "system_constants.h" #include "parse_plural.h" #include "parse_lng.h" #include "util.h" #include "string_tools.h" #include "file_traverser.h" -#include "../shared/standard_paths.h" -#include "../shared/string_conv.h" +#include "standard_paths.h" +#include "string_conv.h" +#include "zenXml/zenxml_io.h" #include "i18n.h" using namespace zen; @@ -28,7 +28,7 @@ using namespace zen; namespace { //global objects -wxString THOUSANDS_SEPARATOR = wxT(","); +std::wstring THOUSANDS_SEPARATOR = L","; class FFSLocale : public TranslationHandler @@ -38,9 +38,9 @@ public: wxLanguage langId() const { return langId_; } - virtual wxString thousandsSeparator() { return THOUSANDS_SEPARATOR; }; + virtual std::wstring thousandsSeparator() { return THOUSANDS_SEPARATOR; }; - virtual wxString translate(const wxString& text) + virtual std::wstring translate(const std::wstring& text) { //look for translation in buffer table const Translation::const_iterator iter = transMapping.find(text); @@ -50,7 +50,7 @@ public: return text; //fallback } - virtual wxString translate(const wxString& singular, const wxString& plural, int n) + virtual std::wstring translate(const std::wstring& singular, const std::wstring& plural, int n) { TranslationPlural::const_iterator iter = transMappingPl.find(std::make_pair(singular, plural)); if (iter != transMappingPl.end()) @@ -64,8 +64,8 @@ public: } private: - typedef std::map<wxString, wxString> Translation; - typedef std::map<std::pair<wxString, wxString>, std::vector<wxString> > TranslationPlural; + typedef std::map<std::wstring, std::wstring> Translation; + typedef std::map<std::pair<std::wstring, std::wstring>, std::vector<std::wstring> > TranslationPlural; Translation transMapping; //map original text |-> translation TranslationPlural transMappingPl; @@ -75,34 +75,17 @@ private: -std::string getFileStream(const wxString& filename) //return empty string on error throw() +FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_(languageId) //throw (lngfile::ParsingError, PluralForm::ParsingError) { std::string inputStream; - - //workaround to get a FILE* from a unicode filename in a portable way - wxFFile langFile(filename, wxT("rb")); - if (langFile.IsOpened()) + try { - FILE* fpInput = langFile.fp(); - - std::vector<char> buffer(50 * 1024); - size_t bytesRead = 0; - do - { - bytesRead = ::fread(&buffer[0], 1, buffer.size(), fpInput); - inputStream.append(&buffer[0], bytesRead); - } - while (bytesRead == buffer.size()); + inputStream = loadStream(filename);; //throw XmlFileError } - return inputStream; -} - - -FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_(languageId) //throw (lngfile::ParsingError, PluralForm::ParsingError) -{ - const std::string inputStream = getFileStream(filename); - if (inputStream.empty()) + catch (...) + { throw lngfile::ParsingError(0, 0); + } lngfile::TransHeader header; lngfile::TranslationMap transInput; @@ -111,21 +94,21 @@ FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_( for (lngfile::TranslationMap::const_iterator i = transInput.begin(); i != transInput.end(); ++i) { - const wxString original = wxString::FromUTF8(i->first.c_str()); - const wxString translation = wxString::FromUTF8(i->second.c_str()); + const std::wstring original = utf8CvrtTo<std::wstring>(i->first); + const std::wstring translation = utf8CvrtTo<std::wstring>(i->second); assert(!translation.empty()); transMapping.insert(std::make_pair(original , translation)); } for (lngfile::TranslationPluralMap::const_iterator i = transPluralInput.begin(); i != transPluralInput.end(); ++i) { - const wxString singular = wxString::FromUTF8(i->first.first.c_str()); - const wxString plural = wxString::FromUTF8(i->first.second.c_str()); + const std::wstring singular = utf8CvrtTo<std::wstring>(i->first.first); + const std::wstring plural = utf8CvrtTo<std::wstring>(i->first.second); const lngfile::PluralForms& plForms = i->second; - std::vector<wxString> plFormsWide; + std::vector<std::wstring> plFormsWide; for (lngfile::PluralForms::const_iterator j = plForms.begin(); j != plForms.end(); ++j) - plFormsWide.push_back(wxString::FromUTF8(j->c_str())); + plFormsWide.push_back(utf8CvrtTo<std::wstring>(*j)); assert(!plFormsWide.empty()); @@ -144,13 +127,13 @@ public: virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) { - if (Zstring(shortName).EndsWith(Zstr(".lng"))) + if (endsWith(fullName, Zstr(".lng"))) lngFiles_.push_back(fullName); } virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) { return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); } - virtual void onError(const wxString& errorText) {} //errors are not really critical in this context + virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } //errors are not really critical in this context private: std::vector<Zstring>& lngFiles_; @@ -197,32 +180,35 @@ ExistingTranslations::ExistingTranslations() std::vector<Zstring> lngFiles; FindLngfiles traverseCallback(lngFiles); - traverseFolder(wxToZ(zen::getResourceDir() + wxT("Languages")), //throw(); + traverseFolder(toZ(zen::getResourceDir() + wxT("Languages")), //throw(); false, //don't follow symlinks traverseCallback); - for (std::vector<Zstring>::const_iterator i = lngFiles.begin(); i != lngFiles.end(); ++i) + for (auto i = lngFiles.begin(); i != lngFiles.end(); ++i) { - const std::string stream = getFileStream(zToWx(*i)); - if (!stream.empty()) + try + { + std::string stream = loadStream(*i);; //throw XmlFileError try { lngfile::TransHeader lngHeader; lngfile::parseHeader(stream, lngHeader); //throw ParsingError - const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(wxString::FromUTF8(lngHeader.localeName.c_str())); + const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(utf8CvrtTo<wxString>(lngHeader.localeName)); if (locInfo) { ExistingTranslations::Entry newEntry; newEntry.languageID = locInfo->Language; - newEntry.languageName = wxString::FromUTF8(lngHeader.languageName.c_str()); - newEntry.languageFile = zToWx(*i); - newEntry.translatorName = wxString::FromUTF8(lngHeader.translatorName.c_str()); - newEntry.languageFlag = wxString::FromUTF8(lngHeader.flagFile.c_str()); + newEntry.languageName = utf8CvrtTo<wxString>(lngHeader.languageName); + newEntry.languageFile = toWx(*i); + newEntry.translatorName = utf8CvrtTo<wxString>(lngHeader.translatorName); + newEntry.languageFlag = utf8CvrtTo<wxString>(lngHeader.flagFile); locMapping.push_back(newEntry); } } catch (lngfile::ParsingError&) {} + } + catch (...) {} } std::sort(locMapping.begin(), locMapping.end(), LessTranslation()); @@ -375,7 +361,7 @@ public: const lconv* localInfo = ::localeconv(); //actually these two parameters are language dependent, but we take system setting to handle all kinds of language derivations - THOUSANDS_SEPARATOR = wxString::FromUTF8(localInfo->thousands_sep); + THOUSANDS_SEPARATOR = utf8CvrtTo<wxString>(localInfo->thousands_sep); // why not working? // THOUSANDS_SEPARATOR = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).thousands_sep(); diff --git a/RealtimeSync/notify.cpp b/shared/notify_removal.cpp index 5969ee08..819604ad 100644 --- a/RealtimeSync/notify.cpp +++ b/shared/notify_removal.cpp @@ -4,10 +4,10 @@ // * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // -#include "notify.h" +#include "notify_removal.h" #include <set> -#include "../shared/last_error.h" -#include "../shared/Loki/ScopeGuard.h" +#include "last_error.h" +#include "Loki/ScopeGuard.h" #include <algorithm> #include <boost/bind.hpp> #include <dbt.h> @@ -51,10 +51,10 @@ public: virtual ~Listener() {} virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) = 0; //throw()! }; - void registerListener(Listener& l); - void unregisterListener(Listener& l); //don't unregister objects with static lifetime + void registerListener(Listener& l) { listener.insert(&l); } + void unregisterListener(Listener& l) { listener.erase(&l); } //don't unregister objects with static lifetime - HWND getWnd() const; //get handle in order to register additional notifications + HWND getWnd() const { return windowHandle; } //get handle in order to register additional notifications private: MessageProvider(); @@ -99,8 +99,7 @@ MessageProvider::MessageProvider() : windowHandle(NULL) { if (process == NULL) - throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") + - zen::getLastErrorFormatted() + wxT(" (GetModuleHandle)")); + throw zen::FileError(std::wstring(L"Could not start monitoring window notifications:") + "\n\n" + getLastErrorFormatted() + " (GetModuleHandle)"); //register the main window class WNDCLASS wc = {}; @@ -109,8 +108,7 @@ MessageProvider::MessageProvider() : wc.lpszClassName = WINDOW_NAME; if (::RegisterClass(&wc) == 0) - throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") + - zen::getLastErrorFormatted() + wxT(" (RegisterClass)")); + throw zen::FileError(std::wstring(L"Could not start monitoring window notifications:") + "\n\n" + getLastErrorFormatted() + " (RegisterClass)"); Loki::ScopeGuard guardClass = Loki::MakeGuard(::UnregisterClass, WINDOW_NAME, process); @@ -128,8 +126,7 @@ MessageProvider::MessageProvider() : process, //HINSTANCE hInstance, NULL); //LPVOID lpParam if (windowHandle == NULL) - throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") + - zen::getLastErrorFormatted() + wxT(" (CreateWindow)")); + throw zen::FileError(std::wstring(L"Could not start monitoring window notifications:") + "\n\n" + getLastErrorFormatted() + " (CreateWindow)"); guardClass.Dismiss(); } @@ -144,27 +141,6 @@ MessageProvider::~MessageProvider() } -inline -void MessageProvider::registerListener(Listener& l) -{ - listener.insert(&l); -} - - -inline -void MessageProvider::unregisterListener(Listener& l) //don't unregister objects with static lifetime -{ - listener.erase(&l); -} - - -inline -HWND MessageProvider::getWnd() const //get handle in order to register additional notifications -{ - return windowHandle; -} - - void MessageProvider::processMessage(UINT message, WPARAM wParam, LPARAM lParam) { std::for_each(listener.begin(), listener.end(), boost::bind(&Listener::onMessage, _1, message, wParam, lParam)); @@ -175,7 +151,7 @@ void MessageProvider::processMessage(UINT message, WPARAM wParam, LPARAM lParam) class NotifyRequestDeviceRemoval::Pimpl : private MessageProvider::Listener { public: - Pimpl(NotifyRequestDeviceRemoval& parent, const std::vector<HANDLE>& openHandles) : //throw (FileError) + Pimpl(NotifyRequestDeviceRemoval& parent, HANDLE hDir) : //throw (FileError) parent_(parent) { MessageProvider::instance().registerListener(*this); //throw (FileError) @@ -184,44 +160,32 @@ public: DEV_BROADCAST_HANDLE filter = {}; filter.dbch_size = sizeof(filter); filter.dbch_devicetype = DBT_DEVTYP_HANDLE; + filter.dbch_handle = hDir; - try - { - for (std::vector<HANDLE>::const_iterator i = openHandles.begin(); i != openHandles.end(); ++i) - { - filter.dbch_handle = *i; - - HDEVNOTIFY hNotfication = ::RegisterDeviceNotification( - MessageProvider::instance().getWnd(), //__in HANDLE hRecipient, - &filter, //__in LPVOID NotificationFilter, - DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags - if (hNotfication == NULL) - { - const DWORD lastError = ::GetLastError(); - if (lastError != ERROR_CALL_NOT_IMPLEMENTED && //fail on SAMBA share: this shouldn't be a showstopper! - lastError != ERROR_SERVICE_SPECIFIC_ERROR && //neither should be fail for "Pogoplug" mapped network drives - lastError != ERROR_INVALID_DATA) //this seems to happen for a NetDrive-mapped FTP server - throw zen::FileError(wxString(wxT("Could not register device removal notifications:")) + wxT("\n\n") + zen::getLastErrorFormatted(lastError)); - } - else - notifications.insert(hNotfication); - } - } - catch (...) + hNotification = ::RegisterDeviceNotification( + MessageProvider::instance().getWnd(), //__in HANDLE hRecipient, + &filter, //__in LPVOID NotificationFilter, + DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags + if (hNotification == NULL) { - std::for_each(notifications.begin(), notifications.end(), ::UnregisterDeviceNotification); - MessageProvider::instance().unregisterListener(*this); //throw() in this case - throw; + const DWORD lastError = ::GetLastError(); + if (lastError != ERROR_CALL_NOT_IMPLEMENTED && //fail on SAMBA share: this shouldn't be a showstopper! + lastError != ERROR_SERVICE_SPECIFIC_ERROR && //neither should be fail for "Pogoplug" mapped network drives + lastError != ERROR_INVALID_DATA) //this seems to happen for a NetDrive-mapped FTP server + throw zen::FileError(std::wstring(L"Could not register device removal notifications:") + "\n\n" + getLastErrorFormatted(lastError)); } } ~Pimpl() { - std::for_each(notifications.begin(), notifications.end(), ::UnregisterDeviceNotification); + ::UnregisterDeviceNotification(hNotification); MessageProvider::instance().unregisterListener(*this); } private: + Pimpl(Pimpl&); + Pimpl& operator=(Pimpl&); + virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) //throw()! { //DBT_DEVICEQUERYREMOVE example: http://msdn.microsoft.com/en-us/library/aa363427(v=VS.85).aspx @@ -241,7 +205,7 @@ private: #else const HDEVNOTIFY requestNotification = body->dbch_hdevnotify; #endif - if (notifications.find(requestNotification) != notifications.end()) //is it for one of our notifications we registered? + if (requestNotification == hNotification) //is it for the notification we registered? switch (wParam) { case DBT_DEVICEQUERYREMOVE: @@ -260,14 +224,14 @@ private: } NotifyRequestDeviceRemoval& parent_; - std::set<HDEVNOTIFY> notifications; + HDEVNOTIFY hNotification; }; //#################################################################################################### -NotifyRequestDeviceRemoval::NotifyRequestDeviceRemoval(const std::vector<HANDLE>& openHandles) +NotifyRequestDeviceRemoval::NotifyRequestDeviceRemoval(HANDLE hDir) { - pimpl.reset(new Pimpl(*this, openHandles)); + pimpl.reset(new Pimpl(*this, hDir)); } diff --git a/RealtimeSync/notify.h b/shared/notify_removal.h index 47f6c3cb..abdf460b 100644 --- a/RealtimeSync/notify.h +++ b/shared/notify_removal.h @@ -12,7 +12,7 @@ #endif #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "../shared/file_error.h" +#include "file_error.h" #include <vector> #include <memory> @@ -21,7 +21,7 @@ class NotifyRequestDeviceRemoval { public: - NotifyRequestDeviceRemoval(const std::vector<HANDLE>& openHandles); //throw (FileError) + NotifyRequestDeviceRemoval(HANDLE hDir); //throw FileError virtual ~NotifyRequestDeviceRemoval(); private: @@ -33,7 +33,7 @@ private: void operator=(NotifyRequestDeviceRemoval&); // class Pimpl; - std::auto_ptr<Pimpl> pimpl; + std::unique_ptr<Pimpl> pimpl; }; diff --git a/shared/pch.h b/shared/pch.h index cd6b73cb..06d6b417 100644 --- a/shared/pch.h +++ b/shared/pch.h @@ -106,7 +106,6 @@ #include <stdexcept> //Boost -#include <memory> #include <boost/scoped_array.hpp> #endif //FFS_PRECOMPILED_HEADER diff --git a/shared/privilege.cpp b/shared/privilege.cpp index c854ad4e..eaeac866 100644 --- a/shared/privilege.cpp +++ b/shared/privilege.cpp @@ -19,10 +19,8 @@ bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw (FileError) if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, TOKEN_QUERY, //__in DWORD DesiredAccess, &hToken)) //__out PHANDLE TokenHandle - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hToken); (void)dummy; //silence warning "unused variable" @@ -32,10 +30,7 @@ bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw (FileError) NULL, //__in_opt LPCTSTR lpSystemName, privilege, //__in LPCTSTR lpName, &luid )) //__out PLUID lpLuid - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); PRIVILEGE_SET priv = {}; priv.PrivilegeCount = 1; @@ -48,10 +43,7 @@ bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw (FileError) hToken, //__in HANDLE ClientToken, &priv, //__inout PPRIVILEGE_SET RequiredPrivileges, &alreadyGranted)) //__out LPBOOL pfResult - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); return alreadyGranted == TRUE; } @@ -63,10 +55,8 @@ void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw (FileError if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, TOKEN_ADJUST_PRIVILEGES, //__in DWORD DesiredAccess, &hToken)) //__out PHANDLE TokenHandle - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hToken); (void)dummy; //silence warning "unused variable" @@ -75,10 +65,7 @@ void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw (FileError NULL, //__in_opt LPCTSTR lpSystemName, privilege, //__in LPCTSTR lpName, &luid )) //__out PLUID lpLuid - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); TOKEN_PRIVILEGES tp = {}; tp.PrivilegeCount = 1; @@ -92,14 +79,8 @@ void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw (FileError 0, //__in DWORD BufferLength, NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState, NULL)) //__out_opt PDWORD ReturnLength - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) //check although previous function returned with success! - { - const wxString errorMessage = wxString(_("Error setting privilege:")) + wxT(" \"") + privilege + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error setting privilege:") + " \"" + privilege + "\"" + "\n\n" + getLastErrorFormatted()); } diff --git a/shared/privilege.h b/shared/privilege.h index 3085c8c8..6ac99e6f 100644 --- a/shared/privilege.h +++ b/shared/privilege.h @@ -45,8 +45,8 @@ private: catch(...) {} } - static bool privilegeIsActive(LPCTSTR privilege); //throw (FileError) - static void setPrivilege(LPCTSTR privilege, bool enable); //throw (FileError) + static bool privilegeIsActive(LPCTSTR privilege); //throw FileError + static void setPrivilege(LPCTSTR privilege, bool enable); //throw FileError typedef std::map<Zstring, bool> PrivBuffType; //bool: enabled by this application diff --git a/shared/recycler.cpp b/shared/recycler.cpp index 32de3f33..cc216d4f 100644 --- a/shared/recycler.cpp +++ b/shared/recycler.cpp @@ -8,7 +8,6 @@ #include <stdexcept> #include <iterator> #include "i18n.h" -#include "string_conv.h" #ifdef FFS_WIN #include "dll_loader.h" @@ -26,26 +25,26 @@ #include <giomm/file.h> #endif +using namespace zen; + namespace { #ifdef FFS_WIN -const std::wstring& getRecyclerDllName() +inline +std::wstring getRecyclerDllName() { - static const std::wstring filename( - util::is64BitBuild ? - L"FileOperation_x64.dll": - L"FileOperation_Win32.dll"); - assert_static(util::is32BitBuild || util::is64BitBuild); - return filename; + return util::is64BitBuild ? + L"FileOperation_x64.dll": + L"FileOperation_Win32.dll"; } bool vistaOrLater() { - OSVERSIONINFO osvi; + OSVERSIONINFO osvi = {}; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); @@ -90,15 +89,15 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw ( static MoveToRecycleBinFct moveToRecycler = NULL; if (!moveToRecycler) - moveToRecycler = util::getDllFun<MoveToRecycleBinFct>(getRecyclerDllName().c_str(), moveToRecycleBinFctName); + moveToRecycler = util::getDllFun<MoveToRecycleBinFct>(getRecyclerDllName(), moveToRecycleBinFctName); static GetLastErrorFct getLastError = NULL; if (!getLastError) - getLastError = util::getDllFun<GetLastErrorFct>(getRecyclerDllName().c_str(), getLastErrorFctName); + getLastError = util::getDllFun<GetLastErrorFct>(getRecyclerDllName(), getLastErrorFctName); if (moveToRecycler == NULL || getLastError == NULL) - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + fileNames[0] + wxT("\"") + //report first file only... better than nothing - wxT("\n\n") + wxString(_("Could not load a required DLL:")) + wxT(" \"") + getRecyclerDllName().c_str() + wxT("\"")); + throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileNames[0] + "\"" + //report first file only... better than nothing + "\n\n" + _("Could not load a required DLL:") + " \"" + getRecyclerDllName() + "\""); //#warning moving long file paths to recycler does not work! clarify! // std::vector<Zstring> temp; @@ -110,8 +109,8 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw ( { wchar_t errorMessage[2000]; getLastError(errorMessage, 2000); - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + fileNames[0] + wxT("\"") + //report first file only... better than nothing - wxT("\n\n") + wxT("(") + errorMessage + wxT(")")); + throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileNames[0] + "\"" + //report first file only... better than nothing + "\n\n" + "(" + errorMessage + ")"); } } else //regular recycle bin usage: available since XP @@ -136,9 +135,9 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw ( fileOp.hNameMappings = NULL; fileOp.lpszProgressTitle = NULL; - if (SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) + if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) { - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + filenameDoubleNull.c_str() + wxT("\"")); //report first file only... better than nothing + throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filenameDoubleNull.c_str() + "\""); //report first file only... better than nothing } } } @@ -167,34 +166,45 @@ bool zen::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileError) if (::lstat(fileToDelete.c_str(), &fileInfo) != 0) return false; //neither file nor any other object with that name existing: no error situation, manual deletion relies on it! - Glib::RefPtr<Gio::File> fileObj = Gio::File::create_for_path(fileToDelete.c_str()); //never fails - try { if (!fileObj->trash()) - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(fileToDelete) + wxT("\"") + - wxT("\n\n") + wxT("(") + wxT("unknown error") + wxT(")")); + throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileToDelete + "\"" + + "\n\n" + "(unknown error)"); } catch (const Glib::Error& errorObj) { //assemble error message - const wxString errorMessage = wxString(wxT("Glib Error Code ")) + wxString::Format(wxT("%i"), errorObj.code()) + wxT(", ") + - wxString::FromUTF8(g_quark_to_string(errorObj.domain())) + wxT(": ") + wxString::FromUTF8(errorObj.what().c_str()); + const std::wstring errorMessage = L"Glib Error Code " + toString<std::wstring>(errorObj.code()) + ", " + + g_quark_to_string(errorObj.domain()) + ": " + errorObj.what(); - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(fileToDelete) + wxT("\"") + - wxT("\n\n") + wxT("(") + errorMessage + wxT(")")); + throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileToDelete + "\"" + + "\n\n" + "(" + errorMessage + ")"); } #endif return true; } -bool zen::recycleBinExists() -{ #ifdef FFS_WIN - return true; -#elif defined FFS_LINUX - return true; -#endif +zen::StatusRecycler zen::recycleBinExists(const Zstring& pathName) +{ + std::vector<wchar_t> buffer(MAX_PATH + 1); + if (::GetVolumePathName(applyLongPathPrefix(pathName).c_str(), //__in LPCTSTR lpszFileName, + &buffer[0], //__out LPTSTR lpszVolumePathName, + static_cast<DWORD>(buffer.size()))) //__in DWORD cchBufferLength + { + Zstring rootPath =&buffer[0]; + if (!rootPath.EndsWith(FILE_NAME_SEPARATOR)) //a trailing backslash is required + rootPath += FILE_NAME_SEPARATOR; + + SHQUERYRBINFO recInfo = {}; + recInfo.cbSize = sizeof(recInfo); + HRESULT rv = ::SHQueryRecycleBin(rootPath.c_str(), //__in_opt LPCTSTR pszRootPath, + &recInfo); //__inout LPSHQUERYRBINFO pSHQueryRBInfo + return rv == S_OK ? STATUS_REC_EXISTS : STATUS_REC_MISSING; + } + return STATUS_REC_UNKNOWN; } +#endif diff --git a/shared/recycler.h b/shared/recycler.h index 85df6f41..da6e3123 100644 --- a/shared/recycler.h +++ b/shared/recycler.h @@ -30,10 +30,20 @@ Linker flag: `pkg-config --libs gtkmm-2.4` */ -bool recycleBinExists(); //test existence of Recycle Bin API on current system - //move a file or folder to Recycle Bin bool moveToRecycleBin(const Zstring& fileToDelete); //return "true" if file/dir was actually deleted; throw (FileError) + + +#ifdef FFS_WIN +enum StatusRecycler +{ + STATUS_REC_EXISTS, + STATUS_REC_MISSING, + STATUS_REC_UNKNOWN +}; + +StatusRecycler recycleBinExists(const Zstring& pathName); //test existence of Recycle Bin API for certain path +#endif } #endif // RECYCLER_H_INCLUDED diff --git a/shared/resolve_path.cpp b/shared/resolve_path.cpp index 95c84e1a..19dc0011 100644 --- a/shared/resolve_path.cpp +++ b/shared/resolve_path.cpp @@ -2,7 +2,6 @@ #include <wx/utils.h> #include <wx/datetime.h> #include "string_conv.h" -#include "system_constants.h" #include "loki/ScopeGuard.h" #ifdef FFS_WIN @@ -17,7 +16,6 @@ #endif using namespace zen; -using namespace common; namespace @@ -73,29 +71,22 @@ bool replaceMacro(wxString& macro) //macro without %-characters, return true if return true; } - if (macro.CmpNoCase(wxT("weekday")) == 0) + auto processPhrase = [&](const wchar_t* phrase, const wchar_t* format) -> bool { - macro = wxDateTime::Now().Format(wxT("%A")); + if (macro.CmpNoCase(phrase) != 0) + return false; + macro = wxDateTime::Now().Format(format); return true; - } - - if (macro.CmpNoCase(wxT("month")) == 0) - { - macro = wxDateTime::Now().Format(wxT("%B")); - return true; - } - - if (macro.CmpNoCase(wxT("week")) == 0) - { - macro = wxDateTime::Now().Format(wxT("%U")); - return true; - } + }; - if (macro.CmpNoCase(wxT("year")) == 0) - { - macro = wxDateTime::Now().Format(wxT("%Y")); - return true; - } + if (processPhrase(L"weekday", L"%A")) return true; + if (processPhrase(L"day" , L"%d")) return true; + if (processPhrase(L"month" , L"%B")) return true; + if (processPhrase(L"week" , L"%U")) return true; + if (processPhrase(L"year" , L"%Y")) return true; + if (processPhrase(L"hour" , L"%H")) return true; + if (processPhrase(L"min" , L"%M")) return true; + if (processPhrase(L"sec" , L"%S")) return true; //try to apply environment variables wxString envValue; @@ -163,7 +154,7 @@ public: devices_.insert(std::make_pair(shortName, fullName)); return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //DON'T traverse into subdirs } - virtual void onError(const wxString& errorText) {} + virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } private: DeviceList& devices_; @@ -285,10 +276,10 @@ Zstring zen::getFormattedDirectoryName(const Zstring& dirname) //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names. //note: don't combine directory formatting with wxFileName, as it doesn't respect //?/ - prefix! - wxString dirnameTmp = zToWx(dirname); + wxString dirnameTmp = toWx(dirname); expandMacros(dirnameTmp); - Zstring output = wxToZ(dirnameTmp); + Zstring output = toZ(dirnameTmp); expandVolumeName(output); diff --git a/shared/serialize.cpp b/shared/serialize.cpp index 634b830b..c2da1202 100644 --- a/shared/serialize.cpp +++ b/shared/serialize.cpp @@ -12,8 +12,7 @@ using namespace zen; void ReadInputStream::throwReadError() const //throw (FileError) { - throw zen::FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") + - wxT("\"") + errorObjName_ + wxT("\"")); + throw zen::FileError(_("Error reading from synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } @@ -35,8 +34,7 @@ ReadInputStream::CharArray ReadInputStream::readArrayC() const //-------------------------------------------------------------------------------------------------------- void WriteOutputStream::throwWriteError() const //throw (FileError) { - throw zen::FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") + - wxT("\"") + errorObjName_ + wxT("\"")); + throw zen::FileError(_("Error writing to synchronization database:") + " \n" + "\"" + errorObjName_.c_str() + "\""); } diff --git a/shared/shadow.cpp b/shared/shadow.cpp index 5827badd..948050b6 100644 --- a/shared/shadow.cpp +++ b/shared/shadow.cpp @@ -6,30 +6,27 @@ // #include "shadow.h" #include <wx/msw/wrapwin.h> //includes "windows.h" -#include "system_constants.h" #include "i18n.h" #include "dll_loader.h" #include <stdexcept> #include "assert_static.h" #include "build_info.h" #include "ShadowCopy\shadow.h" -#include "string_conv.h" #include "Loki/ScopeGuard.h" using shadow::ShadowCopy; -using shadow::WaitingForShadow; -using zen::FileError; +using namespace zen; namespace { bool newerThanXP() { - OSVERSIONINFO osvi; + OSVERSIONINFO osvi = {}; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (GetVersionEx(&osvi)) + if (::GetVersionEx(&osvi)) return osvi.dwMajorVersion > 5 || (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion > 1) ; //XP has majorVersion == 5, minorVersion == 1 @@ -60,7 +57,8 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m } -const std::wstring& getShadowDllName() +inline +std::wstring getShadowDllName() { /* distinguish a bunch of VSS builds: we use XP and Server 2003 implementations... @@ -69,24 +67,17 @@ const std::wstring& getShadowDllName() assert_static(util::is32BitBuild || util::is64BitBuild); - static const std::wstring filename( - newerThanXP() ? - (util::is64BitBuild ? - L"Shadow_Server2003_x64.dll" : - L"Shadow_Server2003_Win32.dll") : + return newerThanXP() ? + (util::is64BitBuild ? + L"Shadow_Server2003_x64.dll" : + L"Shadow_Server2003_Win32.dll") : - (util::is64BitBuild ? - L"Shadow_XP_x64.dll" : - L"Shadow_XP_Win32.dll")); - - - return filename; + (util::is64BitBuild ? + L"Shadow_XP_x64.dll" : + L"Shadow_XP_Win32.dll"); } } - -//############################################################################################################# -ShadowCopy::ShadowCopy(WaitingForShadow* callback) : callback_(callback) {} //############################################################################################################# @@ -107,14 +98,14 @@ public: //check if shadow copy dll was loaded correctly if (createShadowCopy == NULL || releaseShadowCopy == NULL) - throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + - _("Could not load a required DLL:") + wxT(" \"") + getShadowDllName().c_str() + wxT("\"")); + throw FileError(_("Error starting Volume Shadow Copy Service!") + "\n" + + _("Could not load a required DLL:") + " \"" + getShadowDllName() + "\""); //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx) static const bool wow64Active = runningWOW64(); if (wow64Active) - throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + + throw FileError(_("Error starting Volume Shadow Copy Service!") + "\n" + _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.")); //--------------------------------------------------------------------------------------------------------- @@ -129,10 +120,10 @@ public: &backupHandle, errorMessage, 1000)) - throw FileError(wxString(_("Error starting Volume Shadow Copy Service!")) + wxT("\n") + - wxT("(") + errorMessage + wxT(" Volume: \"") + volumeNameFormatted.c_str() + wxT("\")")); + throw FileError(_("Error starting Volume Shadow Copy Service!") + "\n" + + "(" + errorMessage + " Volume: \"" + volumeNameFormatted + "\")"); - shadowVol = Zstring(shadowVolName) + common::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash + shadowVol = Zstring(shadowVolName) + FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash } ~ShadowVolume() @@ -172,19 +163,19 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) if (!::GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName, volumeNameRaw, //__out LPTSTR lpszVolumePathName, 1000)) //__in DWORD cchBufferLength - throw FileError(wxString(_("Could not determine volume name for file:")) + wxT("\n\"") + zToWx(inputFile) + wxT("\"")); + throw FileError(_("Could not determine volume name for file:") + "\n\"" + inputFile + "\""); Zstring volumeNameFormatted = volumeNameRaw; - if (!volumeNameFormatted.EndsWith(common::FILE_NAME_SEPARATOR)) - volumeNameFormatted += common::FILE_NAME_SEPARATOR; + if (!volumeNameFormatted.EndsWith(FILE_NAME_SEPARATOR)) + volumeNameFormatted += FILE_NAME_SEPARATOR; //input file is always absolute! directory formatting takes care of this! Therefore volume name can always be found. const size_t pos = inputFile.find(volumeNameFormatted); //inputFile needs NOT to begin with volumeNameFormatted: consider for example \\?\ prefix! if (pos == Zstring::npos) { - wxString msg = _("Volume name %x not part of filename %y!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(volumeNameFormatted) + wxT("\""), false); - msg.Replace(wxT("%y"), wxString(wxT("\"")) + zToWx(inputFile) + wxT("\""), false); + std::wstring msg = _("Volume name %x not part of filename %y!"); + replace(msg, L"%x", std::wstring(L"\"") + volumeNameFormatted + "\"", false); + replace(msg, L"%y", std::wstring(L"\"") + inputFile + "\"", false); throw FileError(msg); } diff --git a/shared/shadow.h b/shared/shadow.h index 05748fd7..edea4377 100644 --- a/shared/shadow.h +++ b/shared/shadow.h @@ -19,18 +19,10 @@ use in windows build only! namespace shadow { -struct WaitingForShadow -{ - virtual ~WaitingForShadow() {} - virtual void requestUiRefresh() = 0; //allowed to throw exceptions - virtual void reportInfo(const Zstring& text) = 0; -}; - - class ShadowCopy //buffer access to Windows Volume Shadow Copy Service { public: - ShadowCopy(WaitingForShadow* callback); + ShadowCopy() {} Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy @@ -38,8 +30,6 @@ private: ShadowCopy(const ShadowCopy&); ShadowCopy& operator=(const ShadowCopy&); - WaitingForShadow* callback_; - class ShadowVolume; typedef std::map<Zstring, std::shared_ptr<ShadowVolume>, LessFilename> VolNameShadowMap; VolNameShadowMap shadowVol; diff --git a/shared/standard_paths.cpp b/shared/standard_paths.cpp index 44deafff..928dedcc 100644 --- a/shared/standard_paths.cpp +++ b/shared/standard_paths.cpp @@ -6,7 +6,6 @@ // #include "standard_paths.h" #include <wx/stdpaths.h> -#include "system_constants.h" #include "string_conv.h" using namespace zen; @@ -16,14 +15,14 @@ namespace { const wxString& getBinaryDir() //directory containing executable WITH path separator at end { - static wxString instance = zToWx(wxToZ(wxStandardPaths::Get().GetExecutablePath()).BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR); + static wxString instance = beforeLast(wxStandardPaths::Get().GetExecutablePath(), FILE_NAME_SEPARATOR) + toWx(Zstring(FILE_NAME_SEPARATOR)); return instance; } #ifdef FFS_WIN wxString getInstallDir() //root install directory WITH path separator at end { - return getBinaryDir().BeforeLast(common::FILE_NAME_SEPARATOR).BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR; + return getBinaryDir().BeforeLast(FILE_NAME_SEPARATOR).BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR; } #endif } @@ -51,8 +50,8 @@ wxString zen::getResourceDir() { wxString resourceDir = wxStandardPathsBase::Get().GetResourcesDir(); - if (!resourceDir.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) - resourceDir += zToWx(common::FILE_NAME_SEPARATOR); + if (!endsWith(resourceDir, FILE_NAME_SEPARATOR)) + resourceDir += FILE_NAME_SEPARATOR; return resourceDir; } @@ -66,7 +65,7 @@ wxString zen::getConfigDir() #ifdef FFS_WIN return getInstallDir(); #elif defined FFS_LINUX - //wxString(wxT(".")) + zToWx(common::FILE_NAME_SEPARATOR) -> don't use current working directory + //wxString(wxT(".")) + zToWx(FILE_NAME_SEPARATOR) -> don't use current working directory //avoid surprises with GlobalSettings.xml being newly created in each working directory return getBinaryDir(); #endif @@ -77,8 +76,8 @@ wxString zen::getConfigDir() if (!wxDirExists(userDirectory)) ::wxMkdir(userDirectory); //only top directory needs to be created: no recursion necessary - if (!userDirectory.EndsWith(zToWx(common::FILE_NAME_SEPARATOR))) - userDirectory += zToWx(common::FILE_NAME_SEPARATOR); + if (!endsWith(userDirectory, FILE_NAME_SEPARATOR)) + userDirectory += FILE_NAME_SEPARATOR; return userDirectory; } diff --git a/shared/string_conv.h b/shared/string_conv.h index cdfdbbfa..477dda8c 100644 --- a/shared/string_conv.h +++ b/shared/string_conv.h @@ -13,105 +13,13 @@ namespace zen { -//conversion from Zstring to wxString -wxString zToWx(const Zstring& str); -wxString zToWx(const Zchar* str); -wxString zToWx(Zchar ch); -//conversion from wxString to Zstring -Zstring wxToZ(const wxString& str); -Zstring wxToZ(const wxChar* str); -Zstring wxToZ(wxChar ch); +inline wxString operator+(const wxString& lhs, const char* rhs) { return wxString(lhs) += utf8CvrtTo<wxString>(rhs); } +inline wxString operator+(const wxString& lhs, const Zstring& rhs) { return wxString(lhs) += utf8CvrtTo<wxString>(rhs); } - - - - - - - - - - - - - - - - - - - - - - - - -//---------------Inline Implementation--------------------------------------------------- -inline -wxString zToWx(const Zstring& str) -{ -#ifdef FFS_WIN - return cvrtString<wxString>(str); -#elif defined FFS_LINUX - return utf8ToWide<wxString>(str); -#endif -} - - -inline -wxString zToWx(const Zchar* str) -{ -#ifdef FFS_WIN - return cvrtString<wxString>(str); -#elif defined FFS_LINUX - return utf8ToWide<wxString>(str); -#endif -} - - -inline -wxString zToWx(Zchar ch) -{ -#ifdef FFS_WIN - return cvrtString<wxString>(ch); -#elif defined FFS_LINUX - return utf8ToWide<wxString>(ch); -#endif -} - -//----------------------------------------------------------------- -inline -Zstring wxToZ(const wxString& str) -{ -#ifdef FFS_WIN - return cvrtString<Zstring>(str); -#elif defined FFS_LINUX - return wideToUtf8<Zstring>(str); -#endif -} - - -inline -Zstring wxToZ(const wxChar* str) -{ -#ifdef FFS_WIN - return cvrtString<Zstring>(str); -#elif defined FFS_LINUX - return wideToUtf8<Zstring>(str); -#endif -} - - -inline -Zstring wxToZ(wxChar ch) -{ -#ifdef FFS_WIN - return cvrtString<Zstring>(ch); -#elif defined FFS_LINUX - return wideToUtf8<Zstring>(ch); -#endif -} +//conversion between Zstring and wxString +inline wxString toWx(const Zstring& str) { return utf8CvrtTo<wxString>(str); } +inline Zstring toZ(const wxString& str) { return utf8CvrtTo<Zstring>(str); } } #endif // STRINGCONV_H_INCLUDED diff --git a/shared/string_utf8.h b/shared/string_utf8.h index f6f12d8f..26f4c3f2 100644 --- a/shared/string_utf8.h +++ b/shared/string_utf8.h @@ -15,20 +15,22 @@ namespace zen { -//Example: std::string tmp = toUtf8<std::string>(L"abc"); +//convert any(!) "string-like" object into target string by applying a UTF8 conversion (only if necessary!) +template <class TargetString, class SourceString> TargetString utf8CvrtTo(const SourceString& str); + +//convert wide to utf8 string; example: std::string tmp = toUtf8<std::string>(L"abc"); template <class CharString, class WideString> CharString wideToUtf8(const WideString& str); -//Example: std::wstring tmp = utf8To<std::wstring>("abc"); +//convert utf8 string to wide; example: std::wstring tmp = utf8To<std::wstring>("abc"); template <class WideString, class CharString> WideString utf8ToWide(const CharString& str); const char BYTE_ORDER_MARK_UTF8[] = "\xEF\xBB\xBF"; -//convert any(!) "string-like" object into a UTF8 encoded std::string -template <class String> std::string toStdString(const String& str); -//convert a UTF8 encoded std::string to any(!) string-class -template <class String> String stdStringTo(const std::string& str); + + + @@ -190,7 +192,7 @@ Function utf8ToCodePoint(CharIterator first, CharIterator last, Function f) //f }; CodePoint cp = static_cast<Char8>(*first); - switch (getUtf8Len(cp)) + switch (getUtf8Len(static_cast<Char8>(cp))) { case 1: break; @@ -238,13 +240,13 @@ template <class String> class AppendStringIterator: public std::iterator<std::output_iterator_tag, void, void, void, void> { public: - explicit AppendStringIterator (String& x) : str(x) {} - AppendStringIterator& operator= (typename String::value_type value) { str += value; return *this; } + explicit AppendStringIterator (String& x) : str(&x) {} + AppendStringIterator& operator= (typename String::value_type value) { *str += value; return *this; } AppendStringIterator& operator* () { return *this; } AppendStringIterator& operator++ () { return *this; } AppendStringIterator operator++ (int) { return *this; } private: - String& str; + String* str; }; @@ -310,24 +312,24 @@ CharString wideToUtf8(const WideString& str) //------------------------------------------------------------------------------------------- -template <class String> inline -std::string toStdString(const String& str, wchar_t) { return wideToUtf8<std::string>(str); } //convert wide character string to UTF8 +template <class TargetString, class SourceString> inline +TargetString utf8CvrtTo(const SourceString& str, char, wchar_t) { return utf8ToWide<TargetString>(str); } -template <class String> inline -std::string toStdString(const String& str, char) { return cvrtString<std::string>(str); } //directly process string without UTF8 conversion +template <class TargetString, class SourceString> inline +TargetString utf8CvrtTo(const SourceString& str, wchar_t, char) { return wideToUtf8<TargetString>(str); } -template <class String> inline -std::string toStdString(const String& str) { return toStdString(str, typename StringTraits<String>::CharType()); } -//------------------------------------------------------------------------------------------- - -template <class String> inline -String stdStringTo(const std::string& str, wchar_t) { return utf8ToWide<String>(str); } //convert UTF8 to wide character string +template <class TargetString, class SourceString> inline +TargetString utf8CvrtTo(const SourceString& str, char, char) { return cvrtString<TargetString>(str); } -template <class String> inline -String stdStringTo(const std::string& str, char) { return cvrtString<String>(str); } //directly process string without UTF8 conversion +template <class TargetString, class SourceString> inline +TargetString utf8CvrtTo(const SourceString& str, wchar_t, wchar_t) { return cvrtString<TargetString>(str); } -template <class String> inline -String stdStringTo(const std::string& str) { return stdStringTo<String>(str, typename StringTraits<String>::CharType()); } +template <class TargetString, class SourceString> inline +TargetString utf8CvrtTo(const SourceString& str) +{ + return utf8CvrtTo<TargetString>(str, typename StringTraits<SourceString>::CharType(), + typename StringTraits<TargetString>::CharType()); +} } #endif //STRING_UTF8_HEADER_01832479146991573473545 diff --git a/shared/symlink_target.h b/shared/symlink_target.h index 0e98b951..e3a75f81 100644 --- a/shared/symlink_target.h +++ b/shared/symlink_target.h @@ -9,7 +9,6 @@ #include "loki/ScopeGuard.h" #include "last_error.h" -#include "string_conv.h" #include "file_error.h" #include "i18n.h" @@ -63,19 +62,18 @@ namespace //retrieve raw target data of symlink or junction Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw (FileError) { - using zen::zToWx; - using zen::FileError; + using namespace zen; #ifdef FFS_WIN //FSCTL_GET_REPARSE_POINT: http://msdn.microsoft.com/en-us/library/aa364571(VS.85).aspx try //reading certain symlinks requires admin rights! This shall not cause an error in user mode! { //allow access to certain symbolic links/junctions - zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw (FileError) + Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw (FileError) } catch (...) {} - const HANDLE hLink = ::CreateFile(zen::applyLongPathPrefix(linkPath).c_str(), + const HANDLE hLink = ::CreateFile(applyLongPathPrefix(linkPath).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -83,10 +81,8 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw (FileError) FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (hLink == INVALID_HANDLE_VALUE) - { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zen::zToWx(linkPath) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error resolving symbolic link:") + "\n\"" + linkPath + "\"" + "\n\n" + getLastErrorFormatted()); + Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hLink); (void)dummy; //silence warning "unused variable" @@ -102,10 +98,7 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw (FileError) static_cast<DWORD>(buffer.size()), //__in DWORD nOutBufferSize, &bytesReturned, //__out_opt LPDWORD lpBytesReturned, NULL)) //__inout_opt LPOVERLAPPED lpOverlapped - { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zen::zToWx(linkPath) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + zen::getLastErrorFormatted()); - } + throw FileError(_("Error resolving symbolic link:") + "\n\"" + linkPath + "\"" + "\n\n" + getLastErrorFormatted()); REPARSE_DATA_BUFFER& reparseData = *reinterpret_cast<REPARSE_DATA_BUFFER*>(&buffer[0]); //REPARSE_DATA_BUFFER needs to be artificially enlarged! @@ -121,10 +114,7 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw (FileError) reparseData.MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); } else - { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zen::zToWx(linkPath) + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + wxT("Not a symbolic link or junction!")); - } + throw FileError(_("Error resolving symbolic link:") + "\n\"" + linkPath + "\"" + "\n\n" + "Not a symbolic link or junction!"); //absolute symlinks and junctions technically start with \??\ while relative ones do not if (output.StartsWith(Zstr("\\??\\"))) @@ -139,8 +129,9 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw (FileError) const int bytesWritten = ::readlink(linkPath.c_str(), buffer, BUFFER_SIZE); if (bytesWritten < 0 || bytesWritten >= BUFFER_SIZE) { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(linkPath) + wxT("\""); - if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + zen::getLastErrorFormatted(); + std::wstring errorMessage = _("Error resolving symbolic link:") + "\n\"" + linkPath + "\""; + if (bytesWritten < 0) + errorMessage += L"\n\n" + getLastErrorFormatted(); throw FileError(errorMessage); } buffer[bytesWritten] = 0; //set null-terminating char diff --git a/shared/system_constants.h b/shared/system_constants.h deleted file mode 100644 index 9c0cd4a4..00000000 --- a/shared/system_constants.h +++ /dev/null @@ -1,29 +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 SYSTEMCONSTANTS_H_INCLUDED -#define SYSTEMCONSTANTS_H_INCLUDED - -#include "zstring.h" -#include <wx/string.h> - -namespace common -{ -//------------------------------------------------ -// GLOBALS -//------------------------------------------------ -#ifdef FFS_WIN -const Zchar FILE_NAME_SEPARATOR = '\\'; // -const wxChar LINE_BREAK[] = wxT("\r\n"); //internal linkage -#elif defined FFS_LINUX -const Zchar FILE_NAME_SEPARATOR = '/'; -const wxChar LINE_BREAK[] = wxT("\n"); -#endif - -const char BYTE_ORDER_MARK_UTF8[] = "\xEF\xBB\xBF"; -} - -#endif // SYSTEMCONSTANTS_H_INCLUDED diff --git a/shared/taskbar.cpp b/shared/taskbar.cpp index 5767f8c9..969f4bb0 100644 --- a/shared/taskbar.cpp +++ b/shared/taskbar.cpp @@ -33,16 +33,13 @@ bool windows7TaskbarAvailable() } -const std::wstring& getTaskBarDllName() +std::wstring getTaskBarDllName() { assert_static(util::is32BitBuild || util::is64BitBuild); - static const std::wstring filename( - util::is64BitBuild ? - L"Taskbar7_x64.dll" : - L"Taskbar7_Win32.dll"); - - return filename; + return util::is64BitBuild ? + L"Taskbar7_x64.dll" : + L"Taskbar7_Win32.dll"; } } //######################################################################################################## @@ -108,7 +105,7 @@ private: TaskbarProgress::TaskbarProgress(const wxTopLevelWindow& window) : pimpl_(new Pimpl(window)) {} -TaskbarProgress::~TaskbarProgress() {} //std::auto_ptr ... +TaskbarProgress::~TaskbarProgress() {} //std::unique_ptr ... void TaskbarProgress::setStatus(Status status) { diff --git a/shared/taskbar.h b/shared/taskbar.h index b41734b3..90a76d13 100644 --- a/shared/taskbar.h +++ b/shared/taskbar.h @@ -40,7 +40,7 @@ public: private: class Pimpl; - std::auto_ptr<Pimpl> pimpl_; + std::unique_ptr<Pimpl> pimpl_; }; } diff --git a/shared/util.cpp b/shared/util.cpp index 6f066959..faa4074c 100644 --- a/shared/util.cpp +++ b/shared/util.cpp @@ -5,42 +5,32 @@ // ************************************************************************** // #include "util.h" -#include <wx/scrolwin.h> -#include <wx/textctrl.h> -#include <wx/combobox.h> -#include <wx/filepicker.h> +#include "zstring.h" #include "i18n.h" -#include "file_handling.h" -#include "string_conv.h" #include "last_error.h" -#include "check_exist.h" -#include "assert_static.h" -#include "system_constants.h" #include "global_func.h" - #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" #endif + wxString zen::extractJobName(const wxString& configFilename) { - using namespace common; - const wxString shortName = configFilename.AfterLast(FILE_NAME_SEPARATOR); //returns the whole string if seperator not found const wxString jobName = shortName.BeforeLast(wxChar('.')); //returns empty string if seperator not found return jobName.IsEmpty() ? shortName : jobName; } -wxString zen::formatFilesizeToShortString(zen::UInt64 size) +wxString zen::formatFilesizeToShortString(UInt64 size) { - if (to<zen::Int64>(size) < 0) return _("Error"); + if (to<Int64>(size) < 0) return _("Error"); if (size <= 999U) { wxString output = _P("1 Byte", "%x Bytes", to<int>(size)); - output.Replace(wxT("%x"), zen::toStringSep(size)); //no decimal places in case of bytes + output.Replace(wxT("%x"), toStringSep(size)); //no decimal places in case of bytes return output; } else diff --git a/shared/util.h b/shared/util.h index 2aa48af9..25762ce7 100644 --- a/shared/util.h +++ b/shared/util.h @@ -8,12 +8,7 @@ #define UTIL_H_INCLUDED #include <wx/string.h> -#include <wx/textctrl.h> -#include <wx/filepicker.h> -#include <wx/combobox.h> #include <wx/scrolwin.h> -#include <wx/choice.h> -#include "zstring.h" #include "string_tools.h" #include "int64.h" @@ -21,15 +16,15 @@ namespace zen { wxString extractJobName(const wxString& configFilename); -wxString formatFilesizeToShortString(zen::UInt64 filesize); -wxString formatPercentage(zen::Int64 dividend, zen::Int64 divisor); +wxString formatFilesizeToShortString(UInt64 filesize); +wxString formatPercentage(Int64 dividend, Int64 divisor); template <class NumberType> wxString toStringSep(NumberType number); //convert number to wxString including thousands separator void scrollToBottom(wxScrolledWindow* scrWindow); -wxString utcTimeToLocalString(zen::Int64 utcTime); //throw std::runtime_error +wxString utcTimeToLocalString(Int64 utcTime); //throw std::runtime_error } @@ -68,8 +63,7 @@ wxString includeNumberSeparator(const wxString& number); namespace zen { -template <class NumberType> -inline +template <class NumberType> inline wxString toStringSep(NumberType number) { return ffs_Impl::includeNumberSeparator(zen::toString<wxString>(number)); diff --git a/shared/xml_base.cpp b/shared/xml_base.cpp index 3b786fe8..cd9f58a6 100644 --- a/shared/xml_base.cpp +++ b/shared/xml_base.cpp @@ -9,7 +9,6 @@ #include <string_conv.h> #include <file_io.h> #include <i18n.h> -#include <system_constants.h> using namespace zen; @@ -19,14 +18,14 @@ void xmlAccess::loadXmlDocument(const wxString& filename, XmlDoc& doc) //throw F std::string stream; try { - const zen::UInt64 fs = zen::getFilesize(wxToZ(filename)); //throw (FileError) + const zen::UInt64 fs = zen::getFilesize(toZ(filename)); //throw (FileError) { //quick test whether input is an XML: avoid loading large binary files up front! //doesn't correctly handle BOM! (but no issue yet...) const std::string xmlBegin = "<?xml version="; std::vector<char> buffer(xmlBegin.size()); - FileInput inputFile(wxToZ(filename)); //throw (FileError); + FileInput inputFile(toZ(filename)); //throw (FileError); const size_t bytesRead = inputFile.read(&buffer[0], buffer.size()); //throw (FileError) if (bytesRead < xmlBegin.size() || !std::equal(buffer.begin(), buffer.end(), xmlBegin.begin())) throw FfsXmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\"")); @@ -34,7 +33,7 @@ void xmlAccess::loadXmlDocument(const wxString& filename, XmlDoc& doc) //throw F stream.resize(to<size_t>(fs)); - FileInput inputFile(wxToZ(filename)); //throw (FileError); + FileInput inputFile(toZ(filename)); //throw (FileError); const size_t bytesRead = inputFile.read(&stream[0], stream.size()); //throw (FileError) if (bytesRead < to<size_t>(fs)) { @@ -77,7 +76,7 @@ void xmlAccess::saveXmlDocument(const zen::XmlDoc& doc, const wxString& filename bool saveNecessary = true; try { - if (zen::getFilesize(wxToZ(filename)) == stream.size()) //throw FileError + if (zen::getFilesize(toZ(filename)) == stream.size()) //throw FileError try { if (zen::loadStream(filename) == stream) //throw XmlFileError @@ -90,7 +89,7 @@ void xmlAccess::saveXmlDocument(const zen::XmlDoc& doc, const wxString& filename if (saveNecessary) try { - FileOutput outputFile(wxToZ(filename), FileOutput::ACC_OVERWRITE); //throw (FileError) + FileOutput outputFile(toZ(filename), FileOutput::ACC_OVERWRITE); //throw (FileError) outputFile.write(stream.c_str(), stream.length()); // } catch (const FileError& error) //more detailed error messages than with wxWidgets diff --git a/shared/zstring.h b/shared/zstring.h index 66f961fa..841fb8a2 100644 --- a/shared/zstring.h +++ b/shared/zstring.h @@ -110,10 +110,12 @@ void MakeUpper(Zbase<wchar_t, SP, AP>& str); #ifdef FFS_WIN //Windows stores filenames in wide character format typedef wchar_t Zchar; #define Zstr(x) L ## x +const Zchar FILE_NAME_SEPARATOR = L'\\'; #elif defined FFS_LINUX //Linux uses UTF-8 typedef char Zchar; #define Zstr(x) x +const Zchar FILE_NAME_SEPARATOR = '/'; #else #error define platform you are in: FFS_WIN or FFS_LINUX @@ -146,6 +148,7 @@ typedef Zbase<Zchar, StorageRefCount, AllocatorFreeStoreChecked> Zstring; //for + //################################# inline implementation ######################################## #if defined(FFS_WIN) || defined(FFS_LINUX) namespace z_impl diff --git a/structures.h b/structures.h index de2e8149..500cf784 100644 --- a/structures.h +++ b/structures.h @@ -10,7 +10,6 @@ #include <wx/string.h> #include <vector> #include "shared/zstring.h" -#include "shared/system_constants.h" #include "shared/assert_static.h" #include <memory> #include "shared/int64.h" @@ -50,9 +49,9 @@ enum CompareFilesResult //attention make sure these /|\ \|/ three enums match!!! enum CompareDirResult { - DIR_LEFT_SIDE_ONLY = FILE_LEFT_SIDE_ONLY, - DIR_RIGHT_SIDE_ONLY = FILE_RIGHT_SIDE_ONLY, - DIR_EQUAL = FILE_EQUAL, + DIR_LEFT_SIDE_ONLY = FILE_LEFT_SIDE_ONLY, + DIR_RIGHT_SIDE_ONLY = FILE_RIGHT_SIDE_ONLY, + DIR_EQUAL = FILE_EQUAL, DIR_DIFFERENT_METADATA = FILE_DIFFERENT_METADATA //both sides equal, but different metadata only }; @@ -335,13 +334,16 @@ struct MainConfiguration compareVar(CMP_BY_TIME_SIZE), handleSymlinks(SYMLINK_IGNORE), #ifdef FFS_WIN - globalFilter(Zstr("*"), Zstr("\ + globalFilter(Zstr("*"), + Zstr("\ \\System Volume Information\\\n\ -\\RECYCLER\\\n\ \\RECYCLED\\\n\ -\\$Recycle.Bin\\")), //exclude Recycle Bin +\\RECYCLER\\\n\ +\\$Recycle.Bin\\")), #elif defined FFS_LINUX - //exclude nothing + globalFilter(Zstr("*"), + Zstr("/.Trash-*/\n\ + /.recycle/")), #endif handleDeletion(MOVE_TO_RECYCLE_BIN) {} diff --git a/synchronization.cpp b/synchronization.cpp index 293eabf2..d438f947 100644 --- a/synchronization.cpp +++ b/synchronization.cpp @@ -10,7 +10,7 @@ #include <wx/log.h> #include "shared/string_conv.h" #include "shared/util.h" -#include "shared/system_constants.h" +#include "shared/loki/ScopeGuard.h" #include "library/status_handler.h" #include "shared/file_handling.h" #include "shared/resolve_path.h" @@ -272,137 +272,17 @@ std::vector<zen::FolderPairSyncCfg> zen::extractSyncCfg(const MainConfiguration& FolderPairSyncCfg(i->altSyncConfig->syncConfiguration.var == SyncConfig::AUTOMATIC, i->altSyncConfig->handleDeletion, - wxToZ(i->altSyncConfig->customDeletionDirectory)) : + toZ(i->altSyncConfig->customDeletionDirectory)) : FolderPairSyncCfg(mainCfg.syncConfiguration.var == SyncConfig::AUTOMATIC, mainCfg.handleDeletion, - wxToZ(mainCfg.customDeletionDirectory))); + toZ(mainCfg.customDeletionDirectory))); return output; } //------------------------------------------------------------------------------------------------------------ namespace { - -class DiskSpaceNeeded -{ -public: - DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) : - freeSpaceDelLeft_(freeSpaceDelLeft), - freeSpaceDelRight_(freeSpaceDelRight) - { - processRecursively(baseObj); - } - - std::pair<zen::Int64, zen::Int64> getSpaceTotal() const - { - return std::make_pair(spaceNeededLeft, spaceNeededRight); - } - -private: - void processRecursively(const HierarchyObject& hierObj) - { - //don't process directories - - //process files - for (HierarchyObject::SubFileMapping::const_iterator i = hierObj.useSubFiles().begin(); i != hierObj.useSubFiles().end(); ++i) - switch (i->getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); - break; - - case SO_CREATE_NEW_RIGHT: - spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); - break; - - case SO_DELETE_LEFT: - if (freeSpaceDelLeft_) - spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); - break; - - case SO_DELETE_RIGHT: - if (freeSpaceDelRight_) - spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); - break; - - case SO_OVERWRITE_LEFT: - if (freeSpaceDelLeft_) - spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); - spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); - break; - - case SO_OVERWRITE_RIGHT: - if (freeSpaceDelRight_) - spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); - spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); - break; - - case SO_DO_NOTHING: - case SO_EQUAL: - case SO_UNRESOLVED_CONFLICT: - case SO_COPY_METADATA_TO_LEFT: - case SO_COPY_METADATA_TO_RIGHT: - break; - } - - //symbolic links - //[...] - - //recurse into sub-dirs - std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), boost::bind(&DiskSpaceNeeded::processRecursively, this, _1)); - } - - const bool freeSpaceDelLeft_; - const bool freeSpaceDelRight_; - - zen::Int64 spaceNeededLeft; - zen::Int64 spaceNeededRight; -}; - - -//evaluate whether a deletion will actually free space within a volume -bool deletionFreesSpace(const Zstring& baseDir, - const DeletionPolicy handleDeletion, - const Zstring& custDelFolderFmt) -{ - switch (handleDeletion) - { - case DELETE_PERMANENTLY: - return true; - case MOVE_TO_RECYCLE_BIN: - return false; //in general... (unless Recycle Bin is full) - case MOVE_TO_CUSTOM_DIRECTORY: - switch (zen::onSameVolume(baseDir, custDelFolderFmt)) - { - case VOLUME_SAME: - return false; - case VOLUME_DIFFERENT: - return true; //but other volume (custDelFolderFmt) may become full... - case VOLUME_CANT_SAY: - return true; //a rough guess! - } - } - assert(false); - return true; -} - - -std::pair<zen::Int64, zen::Int64> freeDiskSpaceNeeded( - const BaseDirMapping& baseDirObj, - const DeletionPolicy handleDeletion, - const Zstring& custDelFolderFmt) -{ - const bool freeSpaceDelLeft = deletionFreesSpace(baseDirObj.getBaseDir<LEFT_SIDE>(), handleDeletion, custDelFolderFmt); - const bool freeSpaceDelRight = deletionFreesSpace(baseDirObj.getBaseDir<RIGHT_SIDE>(), handleDeletion, custDelFolderFmt); - - return DiskSpaceNeeded(baseDirObj, freeSpaceDelLeft, freeSpaceDelRight).getSpaceTotal(); -} -} -//------------------------------------------------------------------------------------------------------------ - -namespace -{ bool synchronizationNeeded(const SyncStatistics& statisticsTotal) { return statisticsTotal.getCreate() + @@ -446,28 +326,22 @@ FolderPairSyncCfg::FolderPairSyncCfg(bool automaticMode, //----------------------------------------------------------------------------------------------------------- -template <typename Function> -inline +template <typename Function> inline bool tryReportingError(ProcessCallback& handler, Function cmd) //return "true" on success, "false" if error was ignored { while (true) { try { - cmd(); + cmd(); //throw FileError return true; } catch (FileError& error) { - //User abort when copying files or moving files/directories into custom deletion directory: - //windows build: abort if requested, don't show error message if cancelled by user! - //linux build: this refresh is not necessary, because user abort triggers an AbortThisProcess() exception without a FileError() - handler.requestUiRefresh(); //may throw! - - ErrorHandler::Response rv = handler.reportError(error.msg()); //may throw! - if (rv == ErrorHandler::IGNORE_ERROR) + ProcessCallback::Response rv = handler.reportError(error.msg()); //may throw! + if (rv == ProcessCallback::IGNORE_ERROR) return false; - else if (rv == ErrorHandler::RETRY) + else if (rv == ProcessCallback::RETRY) ; //continue with loop else throw std::logic_error("Programming Error: Unknown return value!"); @@ -485,14 +359,14 @@ Zstring getSessionDeletionDir(const Zstring& deletionDirectory, const Zstring& p if (formattedDir.empty()) return Zstring(); //no valid directory for deletion specified (checked later) - if (!formattedDir.EndsWith(common::FILE_NAME_SEPARATOR)) - formattedDir += common::FILE_NAME_SEPARATOR; + if (!formattedDir.EndsWith(FILE_NAME_SEPARATOR)) + formattedDir += FILE_NAME_SEPARATOR; wxString timeNow = wxDateTime::Now().FormatISOTime(); - timeNow.Replace(wxT(":"), wxT("")); + replace(timeNow, L":", L""); const wxString sessionName = wxDateTime::Now().FormatISODate() + wxChar(' ') + timeNow; - formattedDir += prefix + wxToZ(sessionName); + formattedDir += prefix + toZ(sessionName); //ensure that session directory does not yet exist (must be unique) @@ -502,7 +376,7 @@ Zstring getSessionDeletionDir(const Zstring& deletionDirectory, const Zstring& p for (int i = 1; zen::somethingExists(output); ++i) output = formattedDir + Zchar('_') + Zstring::fromNumber(i); - output += common::FILE_NAME_SEPARATOR; + output += FILE_NAME_SEPARATOR; return output; } @@ -520,78 +394,81 @@ SyncProcess::SyncProcess(xmlAccess::OptionalDialogs& warnings, //-------------------------------------------------------------------------------------------------------------- -class DeletionHandling +class DeletionHandling //e.g. generate name of alternate deletion directory (unique for session AND folder pair) { public: - DeletionHandling(const DeletionPolicy handleDel, + DeletionHandling(DeletionPolicy handleDel, const Zstring& custDelFolder, - const Zstring& baseDirLeft, - const Zstring& baseDirRight, + const Zstring& baseDir, //with separator postfix ProcessCallback& procCallback); ~DeletionHandling(); //always (try to) clean up, even if synchronization is aborted! //clean-up temporary directory (recycler bin optimization) - void tryCleanup() const; //throw (FileError) -> call this in non-exceptional coding, i.e. after Sync somewhere! + void tryCleanup(); //throw FileError -> call this in non-exceptional coding, i.e. after Sync somewhere! - template <zen::SelectedSide side> - void removeFile(const FileSystemObject& fileObj) const; //throw (FileError) + void removeFile (const Zstring& relativeName) const; //throw (FileError) + void removeFolder(const Zstring& relativeName) const; //throw (FileError) - template <zen::SelectedSide side> - void removeFolder(const FileSystemObject& dirObj) const; //throw (FileError) + const Zstring& getTxtRemovingFile () const { return txtRemovingFile; } // + const Zstring& getTxtRemovingSymLink() const { return txtRemovingSymlink; } //status text templates + const Zstring& getTxtRemovingDir () const { return txtRemovingDirectory; }; // - const Zstring& getTxtRemovingFile() const; //status text templates - const Zstring& getTxtRemovingSymLink() const; - const Zstring& getTxtRemovingDir() const; //status text templates + //evaluate whether a deletion will actually free space within a volume + bool deletionFreesSpace() const; private: - template <SelectedSide side> - const Zstring& getSessionDir() const; + DeletionPolicy deletionType; + ProcessCallback* procCallback_; //always bound! need assignment operator => not a reference - void tryCleanupLeft() const; //throw (FileError) - void tryCleanupRight() const; //throw (FileError) + Zstring sessionDelDir; //target deletion folder for current folder pair (with timestamp, ends with path separator) - const DeletionPolicy deletionType; - ProcessCallback& procCallback_; - - Zstring sessionDelDirLeft; //target deletion folder for current folder pair (with timestamp, ends with path separator) - Zstring sessionDelDirRight; // + Zstring baseDir_; //with separator postfix //preloaded status texts: Zstring txtRemovingFile; Zstring txtRemovingSymlink; Zstring txtRemovingDirectory; + + bool cleanedUp; }; -DeletionHandling::DeletionHandling(const DeletionPolicy handleDel, +DeletionHandling::DeletionHandling(DeletionPolicy handleDel, const Zstring& custDelFolder, - const Zstring& baseDirLeft, - const Zstring& baseDirRight, + const Zstring& baseDir, //with separator postfix ProcessCallback& procCallback) : deletionType(handleDel), - procCallback_(procCallback) + procCallback_(&procCallback), + baseDir_(baseDir), + cleanedUp(false) { - switch (handleDel) +#ifdef FFS_WIN + if (deletionType == MOVE_TO_RECYCLE_BIN && recycleBinExists(baseDir) != STATUS_REC_EXISTS) + deletionType = DELETE_PERMANENTLY; //Windows' ::SHFileOperation() will do this anyway, but we have a better and faster deletion routine (e.g. on networks) +#endif + + switch (deletionType) { case DELETE_PERMANENTLY: - txtRemovingFile = wxToZ(_("Deleting file %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false); - txtRemovingSymlink = wxToZ(_("Deleting Symbolic Link %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false); - txtRemovingDirectory = wxToZ(_("Deleting folder %x")).Replace( Zstr("%x"), Zstr("\n\"%x\""), false); + txtRemovingFile = toZ(_("Deleting file %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false); + txtRemovingSymlink = toZ(_("Deleting Symbolic Link %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false); + txtRemovingDirectory = toZ(_("Deleting folder %x")).Replace( Zstr("%x"), Zstr("\n\"%x\""), false); break; case MOVE_TO_RECYCLE_BIN: - sessionDelDirLeft = getSessionDeletionDir(baseDirLeft, Zstr("FFS ")); - sessionDelDirRight = getSessionDeletionDir(baseDirRight, Zstr("FFS ")); + sessionDelDir = getSessionDeletionDir(baseDir_, Zstr("FFS ")); - txtRemovingFile = txtRemovingSymlink = txtRemovingDirectory = wxToZ(_("Moving %x to Recycle Bin")).Replace(Zstr("%x"), Zstr("\"%x\""), false); + txtRemovingFile = + txtRemovingSymlink = + txtRemovingDirectory = toZ(_("Moving %x to Recycle Bin")).Replace(Zstr("%x"), Zstr("\"%x\""), false); break; case MOVE_TO_CUSTOM_DIRECTORY: - sessionDelDirLeft = sessionDelDirRight = getSessionDeletionDir(custDelFolder); + sessionDelDir = getSessionDeletionDir(custDelFolder); - txtRemovingFile = wxToZ(_("Moving file %x to user-defined directory %y")). Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); - txtRemovingDirectory = wxToZ(_("Moving folder %x to user-defined directory %y")). Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); - txtRemovingSymlink = wxToZ(_("Moving Symbolic Link %x to user-defined directory %y")).Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); + txtRemovingFile = toZ(_("Moving file %x to user-defined directory %y")). Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); + txtRemovingDirectory = toZ(_("Moving folder %x to user-defined directory %y")). Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); + txtRemovingSymlink = toZ(_("Moving Symbolic Link %x to user-defined directory %y")).Replace(Zstr("%x"), Zstr("\"%x\"\n"), false).Replace(Zstr("%y"), Zstring(Zstr("\"")) + custDelFolder + Zstr("\""), false); break; } } @@ -601,72 +478,21 @@ DeletionHandling::~DeletionHandling() { try //always (try to) clean up, even if synchronization is aborted! { - tryCleanupLeft(); + tryCleanup(); //make sure this stays non-blocking! } catch (...) {} - - try //always clean up BOTH sides separately! - { - tryCleanupRight(); - } - catch (...) {} -} - - -void DeletionHandling::tryCleanup() const //throw(AbortThisProcess) -{ - tryReportingError(procCallback_, boost::bind(&DeletionHandling::tryCleanupLeft, this)); - tryReportingError(procCallback_, boost::bind(&DeletionHandling::tryCleanupRight, this)); } -void DeletionHandling::tryCleanupLeft() const //throw (FileError) +void DeletionHandling::tryCleanup() //throw FileError { - if (deletionType == MOVE_TO_RECYCLE_BIN) //clean-up temporary directory (recycle bin) - zen::moveToRecycleBin(sessionDelDirLeft.BeforeLast(common::FILE_NAME_SEPARATOR)); //throw (FileError) -} - - -void DeletionHandling::tryCleanupRight() const //throw (FileError) -{ - if (deletionType == MOVE_TO_RECYCLE_BIN) //clean-up temporary directory (recycle bin) - zen::moveToRecycleBin(sessionDelDirRight.BeforeLast(common::FILE_NAME_SEPARATOR)); //throw (FileError) -} - - -inline -const Zstring& DeletionHandling::getTxtRemovingFile() const -{ - return txtRemovingFile; -} - - -inline -const Zstring& DeletionHandling::getTxtRemovingDir() const -{ - return txtRemovingDirectory; -} - - -inline -const Zstring& DeletionHandling::getTxtRemovingSymLink() const -{ - return txtRemovingSymlink; -} - - -template <> -inline -const Zstring& DeletionHandling::getSessionDir<LEFT_SIDE>() const -{ - return sessionDelDirLeft; -} + if (!cleanedUp) + { + if (deletionType == MOVE_TO_RECYCLE_BIN) //clean-up temporary directory (recycle bin) + zen::moveToRecycleBin(sessionDelDir.BeforeLast(FILE_NAME_SEPARATOR)); //throw FileError -template <> -inline -const Zstring& DeletionHandling::getSessionDir<RIGHT_SIDE>() const -{ - return sessionDelDirRight; + cleanedUp = true; + } } @@ -677,16 +503,9 @@ class CallbackMoveFileImpl : public CallbackMoveFile //callback functionality public: CallbackMoveFileImpl(ProcessCallback& handler) : statusHandler_(handler) {} - virtual Response requestUiRefresh(const Zstring& currentObject) //DON'T throw exceptions here, at least in Windows build! + virtual void requestUiRefresh(const Zstring& currentObject) //DON'T throw exceptions here, at least in Windows build! { -#ifdef FFS_WIN - statusHandler_.requestUiRefresh(false); //don't allow throwing exception within this call: windows copying callback can't handle this - if (statusHandler_.abortIsRequested()) - return CallbackMoveFile::CANCEL; -#elif defined FFS_LINUX statusHandler_.requestUiRefresh(); //exceptions may be thrown here! -#endif - return CallbackMoveFile::CONTINUE; } private: @@ -709,110 +528,213 @@ private: } -template <zen::SelectedSide side> -void DeletionHandling::removeFile(const FileSystemObject& fileObj) const +void DeletionHandling::removeFile(const Zstring& relativeName) const { - using namespace zen; + const Zstring fullName = baseDir_ + relativeName; switch (deletionType) { case DELETE_PERMANENTLY: - zen::removeFile(fileObj.getFullName<side>()); + zen::removeFile(fullName); break; case MOVE_TO_RECYCLE_BIN: - if (fileExists(fileObj.getFullName<side>())) + if (fileExists(fullName)) { - const Zstring targetFile = getSessionDir<side>() + fileObj.getRelativeName<side>(); //altDeletionDir ends with path separator - const Zstring targetDir = targetFile.BeforeLast(common::FILE_NAME_SEPARATOR); - - if (!dirExists(targetDir)) - createDirectory(targetDir); //throw (FileError) + const Zstring targetFile = sessionDelDir + relativeName; //altDeletionDir ends with path separator + const Zstring targetDir = targetFile.BeforeLast(FILE_NAME_SEPARATOR); try //rename file: no copying!!! { + if (!dirExists(targetDir)) + createDirectory(targetDir); //throw FileError -> may legitimately fail on Linux if permissions are missing + //performance optimization!! Instead of moving each object into recycle bin separately, we rename them ony by one into a //temporary directory and delete this directory only ONCE! - renameFile(fileObj.getFullName<side>(), targetFile); //throw (FileError); + renameFile(fullName, targetFile); //throw (FileError); } catch (...) { //if anything went wrong, move to recycle bin the standard way (single file processing: slow) - moveToRecycleBin(fileObj.getFullName<side>()); //throw (FileError) + moveToRecycleBin(fullName); //throw (FileError) } } break; case MOVE_TO_CUSTOM_DIRECTORY: - if (fileExists(fileObj.getFullName<side>())) + if (fileExists(fullName)) { - const Zstring targetFile = getSessionDir<side>() + fileObj.getRelativeName<side>(); //altDeletionDir ends with path separator - const Zstring targetDir = targetFile.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring targetFile = sessionDelDir + relativeName; //altDeletionDir ends with path separator + const Zstring targetDir = targetFile.BeforeLast(FILE_NAME_SEPARATOR); if (!dirExists(targetDir)) createDirectory(targetDir); //throw (FileError) - CallbackMoveFileImpl callBack(procCallback_); //if file needs to be copied we need callback functionality to update screen and offer abort - moveFile(fileObj.getFullName<side>(), targetFile, true, &callBack); + CallbackMoveFileImpl callBack(*procCallback_); //if file needs to be copied we need callback functionality to update screen and offer abort + moveFile(fullName, targetFile, true, &callBack); } break; } } -template <zen::SelectedSide side> -void DeletionHandling::removeFolder(const FileSystemObject& dirObj) const +void DeletionHandling::removeFolder(const Zstring& relativeName) const { - using namespace zen; + const Zstring fullName = baseDir_ + relativeName; switch (deletionType) { case DELETE_PERMANENTLY: { - CallbackRemoveDirImpl remDirCallback(procCallback_); - removeDirectory(dirObj.getFullName<side>(), &remDirCallback); + CallbackRemoveDirImpl remDirCallback(*procCallback_); + removeDirectory(fullName, &remDirCallback); } break; case MOVE_TO_RECYCLE_BIN: - if (dirExists(dirObj.getFullName<side>())) + if (dirExists(fullName)) { - const Zstring targetDir = getSessionDir<side>() + dirObj.getRelativeName<side>(); - const Zstring targetSuperDir = targetDir.BeforeLast(common::FILE_NAME_SEPARATOR); - - if (!dirExists(targetSuperDir)) - createDirectory(targetSuperDir); //throw (FileError) + const Zstring targetDir = sessionDelDir + relativeName; + const Zstring targetSuperDir = targetDir.BeforeLast(FILE_NAME_SEPARATOR); try //rename directory: no copying!!! { + if (!dirExists(targetSuperDir)) + createDirectory(targetSuperDir); //throw FileError -> may legitimately fail on Linux if permissions are missing + //performance optimization!! Instead of moving each object into recycle bin separately, we rename them ony by one into a //temporary directory and delete this directory only ONCE! - renameFile(dirObj.getFullName<side>(), targetDir); //throw (FileError); + renameFile(fullName, targetDir); //throw (FileError); } catch (...) { //if anything went wrong, move to recycle bin the standard way (single file processing: slow) - moveToRecycleBin(dirObj.getFullName<side>()); //throw (FileError) + moveToRecycleBin(fullName); //throw (FileError) } } break; case MOVE_TO_CUSTOM_DIRECTORY: - if (dirExists(dirObj.getFullName<side>())) + if (dirExists(fullName)) { - const Zstring targetDir = getSessionDir<side>() + dirObj.getRelativeName<side>(); - const Zstring targetSuperDir = targetDir.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring targetDir = sessionDelDir + relativeName; + const Zstring targetSuperDir = targetDir.BeforeLast(FILE_NAME_SEPARATOR); if (!dirExists(targetSuperDir)) createDirectory(targetSuperDir); //throw (FileError) - CallbackMoveFileImpl callBack(procCallback_); //if files need to be copied, we need callback functionality to update screen and offer abort - moveDirectory(dirObj.getFullName<side>(), targetDir, true, &callBack); + CallbackMoveFileImpl callBack(*procCallback_); //if files need to be copied, we need callback functionality to update screen and offer abort + moveDirectory(fullName, targetDir, true, &callBack); } break; } } + +//evaluate whether a deletion will actually free space within a volume +bool DeletionHandling::deletionFreesSpace() const +{ + switch (deletionType) + { + case DELETE_PERMANENTLY: + return true; + case MOVE_TO_RECYCLE_BIN: + return false; //in general... (unless Recycle Bin is full) + case MOVE_TO_CUSTOM_DIRECTORY: + switch (zen::onSameVolume(baseDir_, sessionDelDir)) + { + case VOLUME_SAME: + return false; + case VOLUME_DIFFERENT: + return true; //but other volume (sessionDelDir) may become full... + case VOLUME_CANT_SAY: + return true; //a rough guess! + } + } + assert(false); + return true; +} +//------------------------------------------------------------------------------------------------------------ + +namespace +{ + +class DiskSpaceNeeded +{ +public: + DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) : + freeSpaceDelLeft_(freeSpaceDelLeft), + freeSpaceDelRight_(freeSpaceDelRight) + { + processRecursively(baseObj); + } + + std::pair<zen::Int64, zen::Int64> getSpaceTotal() const + { + return std::make_pair(spaceNeededLeft, spaceNeededRight); + } + +private: + void processRecursively(const HierarchyObject& hierObj) + { + //don't process directories + + //process files + for (HierarchyObject::SubFileMapping::const_iterator i = hierObj.useSubFiles().begin(); i != hierObj.useSubFiles().end(); ++i) + switch (i->getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_CREATE_NEW_LEFT: + spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_CREATE_NEW_RIGHT: + spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DELETE_LEFT: + if (freeSpaceDelLeft_) + spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DELETE_RIGHT: + if (freeSpaceDelRight_) + spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_OVERWRITE_LEFT: + if (freeSpaceDelLeft_) + spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_OVERWRITE_RIGHT: + if (freeSpaceDelRight_) + spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + break; + } + + //symbolic links + //[...] + + //recurse into sub-dirs + std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), boost::bind(&DiskSpaceNeeded::processRecursively, this, _1)); + } + + const bool freeSpaceDelLeft_; + const bool freeSpaceDelRight_; + + zen::Int64 spaceNeededLeft; + zen::Int64 spaceNeededRight; +}; +} //---------------------------------------------------------------------------------------- //test if current sync-line will result in deletion of files or @@ -841,9 +763,11 @@ bool diskSpaceIsReduced(const FileMapping& fileObj) case SO_COPY_METADATA_TO_RIGHT: return false; } + assert(false); return false; //dummy } + inline bool diskSpaceIsReduced(const DirMapping& dirObj) { @@ -856,15 +780,16 @@ bool diskSpaceIsReduced(const DirMapping& dirObj) case SO_OVERWRITE_LEFT: case SO_OVERWRITE_RIGHT: assert(false); - case SO_UNRESOLVED_CONFLICT: case SO_CREATE_NEW_LEFT: case SO_CREATE_NEW_RIGHT: case SO_DO_NOTHING: case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: case SO_COPY_METADATA_TO_LEFT: case SO_COPY_METADATA_TO_RIGHT: return false; } + assert(false); return false; //dummy } //--------------------------------------------------------------------------------------------------------------- @@ -877,36 +802,45 @@ public: #ifdef FFS_WIN shadow::ShadowCopy* shadowCopyHandler, #endif - const DeletionHandling& delHandling) : + const DeletionHandling& delHandlingLeft, + const DeletionHandling& delHandlingRight) : procCallback_(syncProc.procCallback), #ifdef FFS_WIN shadowCopyHandler_(shadowCopyHandler), #endif - delHandling_(delHandling), + delHandlingLeft_(delHandlingLeft), + delHandlingRight_(delHandlingRight), verifyCopiedFiles_(syncProc.verifyCopiedFiles_), copyFilePermissions_(syncProc.copyFilePermissions_), - txtCopyingFile (wxToZ(_("Copying new file %x to %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), - txtCopyingLink (wxToZ(_("Copying new Symbolic Link %x to %y")).Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), - txtOverwritingFile(wxToZ(_("Overwriting file %x in %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), - txtOverwritingLink(wxToZ(_("Overwriting Symbolic Link %x in %y")).Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), - txtCreatingFolder (wxToZ(_("Creating folder %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)), - txtVerifying (wxToZ(_("Verifying file %x")). Replace(Zstr("%x"), Zstr("\n\"%x\""), false)), - txtWritingAttributes(wxToZ(_("Updating attributes of %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)) {} + txtCopyingFile (toZ(_("Copying new file %x to %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), + txtCopyingLink (toZ(_("Copying new Symbolic Link %x to %y")).Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), + txtOverwritingFile(toZ(_("Overwriting file %x in %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), + txtOverwritingLink(toZ(_("Overwriting Symbolic Link %x in %y")).Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)), + txtCreatingFolder (toZ(_("Creating folder %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)), + txtVerifying (toZ(_("Verifying file %x")). Replace(Zstr("%x"), Zstr("\n\"%x\""), false)), + txtWritingAttributes(toZ(_("Updating attributes of %x")).Replace(Zstr("%x"), Zstr("\n\"%x\""), false)) {} - template <bool reduceDiskSpace> //"true" if files deletion shall happen only void startSync(BaseDirMapping& baseMap) { - execute<reduceDiskSpace>(baseMap); + //loop through all files twice; reason: first delete files (or overwrite big ones with smaller ones), then copy rest + execute<FIRST_PASS >(baseMap); + execute<SECOND_PASS>(baseMap); } private: - template <bool reduceDiskSpace> //"true" if files deletion shall happen only + enum PassId + { + FIRST_PASS, //delete files + SECOND_PASS //create, modify + }; + + template <PassId pass> void execute(HierarchyObject& hierObj); - void synchronizeFile(FileMapping& fileObj) const; - void synchronizeLink(SymLinkMapping& linkObj) const; - void synchronizeFolder(DirMapping& dirObj) const; + void synchronizeFile (FileMapping& fileObj) const; + void synchronizeLink (SymLinkMapping& linkObj) const; + void synchronizeFolder(DirMapping& dirObj) const; //more low level helper template <zen::SelectedSide side> @@ -920,7 +854,8 @@ private: #ifdef FFS_WIN shadow::ShadowCopy* shadowCopyHandler_; //optional! #endif - const DeletionHandling& delHandling_; + const DeletionHandling& delHandlingLeft_; + const DeletionHandling& delHandlingRight_; const bool verifyCopiedFiles_; const bool copyFilePermissions_; @@ -936,63 +871,34 @@ private: }; -template <bool reduceDiskSpace> //"true" if file deletion happens only +template <SynchronizeFolderPair::PassId pass> void SynchronizeFolderPair::execute(HierarchyObject& hierObj) { //synchronize files: - for (HierarchyObject::SubFileMapping::iterator i = hierObj.useSubFiles().begin(); i != hierObj.useSubFiles().end(); ++i) + std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), + [&](FileMapping& fileObj) { - const bool letsDoThis = reduceDiskSpace == diskSpaceIsReduced(*i); + const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(fileObj); //to be deleted files on first pass, rest on second! if (letsDoThis) - tryReportingError(procCallback_, boost::bind(&SynchronizeFolderPair::synchronizeFile, this, boost::ref(*i))); - } + tryReportingError(procCallback_, [&]() { synchronizeFile(fileObj); }); + }); //synchronize symbolic links: (process in second step only) - if (!reduceDiskSpace) - for (HierarchyObject::SubLinkMapping::iterator i = hierObj.useSubLinks().begin(); i != hierObj.useSubLinks().end(); ++i) - tryReportingError(procCallback_, boost::bind(&SynchronizeFolderPair::synchronizeLink, this, boost::ref(*i))); + if (pass == SECOND_PASS) + std::for_each(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(), + [&](SymLinkMapping& linkObj) { tryReportingError(procCallback_, [&]() { synchronizeLink(linkObj); }); }); //synchronize folders: - for (HierarchyObject::SubDirMapping::iterator i = hierObj.useSubDirs().begin(); i != hierObj.useSubDirs().end(); ++i) + std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), + [&](DirMapping& dirObj) { - const SyncOperation syncOp = i->getSyncOperation(); - - //ensure folder creation happens in second pass, to enable time adaption below - const bool letsDoThis = reduceDiskSpace == diskSpaceIsReduced(*i); - - if (letsDoThis) - tryReportingError(procCallback_, boost::bind(&SynchronizeFolderPair::synchronizeFolder, this, boost::ref(*i))); - - //recursive synchronization: - execute<reduceDiskSpace>(*i); + const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(dirObj); //to be deleted files on first pass, rest on second! + if (letsDoThis) //running folder creation on first pass only, works, but looks strange for initial mirror sync when all folders are created at once + tryReportingError(procCallback_, [&]() { synchronizeFolder(dirObj); }); - //adapt folder modification dates: apply AFTER all subobjects have been synced to preserve folder modification date! - if (letsDoThis) - try - { - switch (syncOp) - { - case SO_CREATE_NEW_LEFT: - case SO_COPY_METADATA_TO_LEFT: - copyFileTimes(i->getFullName<RIGHT_SIDE>(), i->getFullName<LEFT_SIDE>(), true); //deref symlinks; throw (FileError) - break; - case SO_CREATE_NEW_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - copyFileTimes(i->getFullName<LEFT_SIDE>(), i->getFullName<RIGHT_SIDE>(), true); //deref symlinks; throw (FileError) - break; - case SO_OVERWRITE_RIGHT: - case SO_OVERWRITE_LEFT: - assert(false); - case SO_UNRESOLVED_CONFLICT: - case SO_DELETE_LEFT: - case SO_DELETE_RIGHT: - case SO_DO_NOTHING: - case SO_EQUAL: - break; - } - } - catch (...) {} - } + //recursion! + this->execute<pass>(dirObj); + }); } @@ -1013,7 +919,7 @@ public: void operator()() const { //delete target and copy source - delHandling_.removeFile<side>(fileObj_); //throw (FileError) + delHandling_.removeFile(fileObj_.getObjRelativeName()); //throw (FileError) fileObj_.removeObject<side>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) } @@ -1036,9 +942,8 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const statusText = txtCopyingFile; statusText.Replace(Zstr("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(Zstr("%y"), target.BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), target.BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copyFileUpdating(fileObj.getFullName<RIGHT_SIDE>(), target, NullCommand(), //no target to delete @@ -1050,9 +955,8 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const statusText = txtCopyingFile; statusText.Replace(Zstr("%x"), fileObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(Zstr("%y"), target.BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), target.BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copyFileUpdating(fileObj.getFullName<LEFT_SIDE>(), target, NullCommand(), //no target to delete @@ -1060,21 +964,19 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const break; case SO_DELETE_LEFT: - statusText = delHandling_.getTxtRemovingFile(); + statusText = delHandlingLeft_.getTxtRemovingFile(); statusText.Replace(Zstr("%x"), fileObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); - delHandling_.removeFile<LEFT_SIDE>(fileObj); //throw (FileError) + delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw (FileError) break; case SO_DELETE_RIGHT: - statusText = delHandling_.getTxtRemovingFile(); + statusText = delHandlingRight_.getTxtRemovingFile(); statusText.Replace(Zstr("%x"), fileObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); - delHandling_.removeFile<RIGHT_SIDE>(fileObj); //throw (FileError) + delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw (FileError) break; case SO_OVERWRITE_LEFT: @@ -1082,12 +984,11 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const statusText = txtOverwritingFile; statusText.Replace(Zstr("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(Zstr("%y"), fileObj.getFullName<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), fileObj.getFullName<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copyFileUpdating(fileObj.getFullName<RIGHT_SIDE>(), target, - DelTargetCommand<LEFT_SIDE>(fileObj, delHandling_), //delete target at appropriate time + DelTargetCommand<LEFT_SIDE>(fileObj, delHandlingLeft_), //delete target at appropriate time fileObj.getFileSize<RIGHT_SIDE>()); break; @@ -1096,24 +997,22 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const statusText = txtOverwritingFile; statusText.Replace(Zstr("%x"), fileObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(Zstr("%y"), fileObj.getFullName<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), fileObj.getFullName<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copyFileUpdating(fileObj.getFullName<LEFT_SIDE>(), target, - DelTargetCommand<RIGHT_SIDE>(fileObj, delHandling_), //delete target at appropriate time + DelTargetCommand<RIGHT_SIDE>(fileObj, delHandlingRight_), //delete target at appropriate time fileObj.getFileSize<LEFT_SIDE>()); break; case SO_COPY_METADATA_TO_LEFT: statusText = txtWritingAttributes; statusText.Replace(Zstr("%x"), fileObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) renameFile(fileObj.getFullName<LEFT_SIDE>(), - fileObj.getFullName<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + fileObj.getShortName<RIGHT_SIDE>()); //throw (FileError); + fileObj.getFullName<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<RIGHT_SIDE>()); //throw (FileError); if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) ////respect 2 second FAT/FAT32 precision copyFileTimes(fileObj.getFullName<RIGHT_SIDE>(), fileObj.getFullName<LEFT_SIDE>(), true); //deref symlinks; throw (FileError) @@ -1122,12 +1021,11 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const case SO_COPY_METADATA_TO_RIGHT: statusText = txtWritingAttributes; statusText.Replace(Zstr("%x"), fileObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) renameFile(fileObj.getFullName<RIGHT_SIDE>(), - fileObj.getFullName<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + fileObj.getShortName<LEFT_SIDE>()); //throw (FileError); + fileObj.getFullName<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<LEFT_SIDE>()); //throw (FileError); if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) ////respect 2 second FAT/FAT32 precision copyFileTimes(fileObj.getFullName<LEFT_SIDE>(), fileObj.getFullName<RIGHT_SIDE>(), true); //deref symlinks; throw (FileError) @@ -1145,6 +1043,7 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const //progress indicator update //indicator is updated only if file is sync'ed correctly (and if some sync was done)! procCallback_.updateProcessedData(1, 0); //processed data is communicated in subfunctions! + procCallback_.requestUiRefresh(); //may throw } @@ -1160,9 +1059,8 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const statusText = txtCopyingLink; statusText.Replace(Zstr("%x"), linkObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(Zstr("%y"), target.BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), target.BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copySymlink(linkObj.getFullName<RIGHT_SIDE>(), target, linkObj.getLinkType<RIGHT_SIDE>()); break; @@ -1172,27 +1070,24 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const statusText = txtCopyingLink; statusText.Replace(Zstr("%x"), linkObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(Zstr("%y"), target.BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), target.BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); copySymlink(linkObj.getFullName<LEFT_SIDE>(), target, linkObj.getLinkType<LEFT_SIDE>()); break; case SO_DELETE_LEFT: - statusText = delHandling_.getTxtRemovingSymLink(); + statusText = delHandlingLeft_.getTxtRemovingSymLink(); statusText.Replace(Zstr("%x"), linkObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); deleteSymlink<LEFT_SIDE>(linkObj); //throw (FileError) break; case SO_DELETE_RIGHT: - statusText = delHandling_.getTxtRemovingSymLink(); + statusText = delHandlingRight_.getTxtRemovingSymLink(); statusText.Replace(Zstr("%x"), linkObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); deleteSymlink<RIGHT_SIDE>(linkObj); //throw (FileError) break; @@ -1202,9 +1097,8 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const statusText = txtOverwritingLink; statusText.Replace(Zstr("%x"), linkObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(Zstr("%y"), linkObj.getFullName<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), linkObj.getFullName<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); deleteSymlink<LEFT_SIDE>(linkObj); //throw (FileError) linkObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) @@ -1217,9 +1111,8 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const statusText = txtOverwritingLink; statusText.Replace(Zstr("%x"), linkObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(Zstr("%y"), linkObj.getFullName<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + statusText.Replace(Zstr("%y"), linkObj.getFullName<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); deleteSymlink<RIGHT_SIDE>(linkObj); //throw (FileError) linkObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) @@ -1230,12 +1123,11 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const case SO_COPY_METADATA_TO_LEFT: statusText = txtWritingAttributes; statusText.Replace(Zstr("%x"), linkObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) renameFile(linkObj.getFullName<LEFT_SIDE>(), - linkObj.getFullName<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + linkObj.getShortName<RIGHT_SIDE>()); //throw (FileError); + linkObj.getFullName<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<RIGHT_SIDE>()); //throw (FileError); if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) ////respect 2 second FAT/FAT32 precision copyFileTimes(linkObj.getFullName<RIGHT_SIDE>(), linkObj.getFullName<LEFT_SIDE>(), false); //don't deref symlinks; throw (FileError) @@ -1244,12 +1136,11 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const case SO_COPY_METADATA_TO_RIGHT: statusText = txtWritingAttributes; statusText.Replace(Zstr("%x"), linkObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) renameFile(linkObj.getFullName<RIGHT_SIDE>(), - linkObj.getFullName<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + linkObj.getShortName<LEFT_SIDE>()); //throw (FileError); + linkObj.getFullName<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<LEFT_SIDE>()); //throw (FileError); if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) ////respect 2 second FAT/FAT32 precision copyFileTimes(linkObj.getFullName<LEFT_SIDE>(), linkObj.getFullName<RIGHT_SIDE>(), false); //don't deref symlinks; throw (FileError) @@ -1267,6 +1158,7 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const //progress indicator update //indicator is updated only if file is sync'ed correctly (and if some sync was done)! procCallback_.updateProcessedData(1, 0); //processed data is communicated in subfunctions! + procCallback_.requestUiRefresh(); //may throw } @@ -1283,12 +1175,11 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const statusText = txtCreatingFolder; statusText.Replace(Zstr("%x"), target, false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); //some check to catch the error that directory on source has been deleted externally after "compare"... if (!zen::dirExists(dirObj.getFullName<RIGHT_SIDE>())) - throw FileError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(dirObj.getFullName<RIGHT_SIDE>()) + wxT("\"")); + throw FileError(_("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<RIGHT_SIDE>() + "\""); createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), copyFilePermissions_); //no symlink copying! break; @@ -1297,77 +1188,72 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const statusText = txtCreatingFolder; statusText.Replace(Zstr("%x"), target, false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); //some check to catch the error that directory on source has been deleted externally after "compare"... if (!zen::dirExists(dirObj.getFullName<LEFT_SIDE>())) - throw FileError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(dirObj.getFullName<LEFT_SIDE>()) + wxT("\"")); + throw FileError(_("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<LEFT_SIDE>() + "\""); createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), copyFilePermissions_); //no symlink copying! break; + case SO_COPY_METADATA_TO_LEFT: + statusText = txtWritingAttributes; + statusText.Replace(Zstr("%x"), dirObj.getFullName<LEFT_SIDE>(), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); + + if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) + renameFile(dirObj.getFullName<LEFT_SIDE>(), + dirObj.getFullName<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<RIGHT_SIDE>()); //throw (FileError); + //copyFileTimes(dirObj.getFullName<RIGHT_SIDE>(), dirObj.getFullName<LEFT_SIDE>(), true); //throw (FileError) -> is executed after sub-objects have finished synchronization + break; + + case SO_COPY_METADATA_TO_RIGHT: + statusText = txtWritingAttributes; + statusText.Replace(Zstr("%x"), dirObj.getFullName<RIGHT_SIDE>(), false); + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); + + if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) + renameFile(dirObj.getFullName<RIGHT_SIDE>(), + dirObj.getFullName<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<LEFT_SIDE>()); //throw (FileError); + //copyFileTimes(dirObj.getFullName<LEFT_SIDE>(), dirObj.getFullName<RIGHT_SIDE>(), true); //throw (FileError) -> is executed after sub-objects have finished synchronization + break; + case SO_DELETE_LEFT: //status information - statusText = delHandling_.getTxtRemovingDir(); + statusText = delHandlingLeft_.getTxtRemovingDir(); statusText.Replace(Zstr("%x"), dirObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); - delHandling_.removeFolder<LEFT_SIDE>(dirObj); //throw (FileError) + delHandlingLeft_.removeFolder(dirObj.getObjRelativeName()); //throw (FileError) { //progress indicator update: DON'T forget to notify about implicitly deleted objects! const SyncStatistics subObjects(dirObj); //...then remove everything dirObj.useSubFiles().clear(); dirObj.useSubLinks().clear(); - dirObj.useSubDirs().clear(); + dirObj.useSubDirs ().clear(); procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); } break; case SO_DELETE_RIGHT: //status information - statusText = delHandling_.getTxtRemovingDir(); + statusText = delHandlingRight_.getTxtRemovingDir(); statusText.Replace(Zstr("%x"), dirObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); - delHandling_.removeFolder<RIGHT_SIDE>(dirObj); //throw (FileError) + delHandlingRight_.removeFolder(dirObj.getObjRelativeName()); //throw (FileError) { //progress indicator update: DON'T forget to notify about implicitly deleted objects! const SyncStatistics subObjects(dirObj); //...then remove everything dirObj.useSubFiles().clear(); dirObj.useSubLinks().clear(); - dirObj.useSubDirs().clear(); + dirObj.useSubDirs ().clear(); procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); } break; - case SO_COPY_METADATA_TO_LEFT: - statusText = txtWritingAttributes; - statusText.Replace(Zstr("%x"), dirObj.getFullName<LEFT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh - - if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(dirObj.getFullName<LEFT_SIDE>(), - dirObj.getFullName<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + dirObj.getShortName<RIGHT_SIDE>()); //throw (FileError); - //copyFileTimes(dirObj.getFullName<RIGHT_SIDE>(), dirObj.getFullName<LEFT_SIDE>(), true); //throw (FileError) -> is executed after sub-objects have finished synchronization - break; - - case SO_COPY_METADATA_TO_RIGHT: - statusText = txtWritingAttributes; - statusText.Replace(Zstr("%x"), dirObj.getFullName<RIGHT_SIDE>(), false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh - - if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(dirObj.getFullName<RIGHT_SIDE>(), - dirObj.getFullName<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR) + common::FILE_NAME_SEPARATOR + dirObj.getShortName<LEFT_SIDE>()); //throw (FileError); - //copyFileTimes(dirObj.getFullName<LEFT_SIDE>(), dirObj.getFullName<RIGHT_SIDE>(), true); //throw (FileError) -> is executed after sub-objects have finished synchronization - break; - case SO_OVERWRITE_RIGHT: case SO_OVERWRITE_LEFT: assert(false); @@ -1383,6 +1269,7 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const //progress indicator update //indicator is updated only if directory is sync'ed correctly (and if some work was done)! procCallback_.updateProcessedData(1, 0); //each call represents one processed file + procCallback_.requestUiRefresh(); //may throw } @@ -1397,11 +1284,11 @@ bool dataLossPossible(const Zstring& dirName, const SyncStatistics& folderPairSt namespace { -void makeSameLength(wxString& first, wxString& second) +void makeSameLength(std::wstring& first, std::wstring& second) { const size_t maxPref = std::max(first.length(), second.length()); - first.Pad(maxPref - first.length(), wxT(' '), true); - second.Pad(maxPref - second.length(), wxT(' '), true); + first .resize(maxPref, L' '); + second.resize(maxPref, L' '); } struct LessDependentDirectory : public std::binary_function<Zstring, Zstring, bool> @@ -1426,27 +1313,24 @@ struct EqualDependentDirectory : public std::binary_function<Zstring, Zstring, b class EnforceUpdateDatabase { public: - EnforceUpdateDatabase(const BaseDirMapping& baseMap, ProcessCallback& procCallback) : + EnforceUpdateDatabase(const BaseDirMapping& baseMap) : dbWasWritten(false), - baseMap_(baseMap), - procCallback_(procCallback) {} + baseMap_(baseMap) {} ~EnforceUpdateDatabase() { try { - tryWriteDB(); + tryWriteDB(); //throw FileError, keep non-blocking!!! } catch (...) {} } - void tryWriteDB() //(try to gracefully) write db file; may throw in error-callback! + void tryWriteDB() //(try to gracefully) write db file; throw FileError { if (!dbWasWritten) { - procCallback_.reportInfo(wxToZ(_("Generating database..."))); - procCallback_.forceUiRefresh(); - tryReportingError(procCallback_, boost::bind(zen::saveToDisk, boost::cref(baseMap_))); //may throw in error-callback! + zen::saveToDisk(baseMap_); //throw FileError dbWasWritten = true; } } @@ -1454,7 +1338,6 @@ public: private: bool dbWasWritten; const BaseDirMapping& baseMap_; - ProcessCallback& procCallback_; }; } @@ -1480,11 +1363,30 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf ProcessCallback::PROCESS_SYNCHRONIZING); if (!synchronizationNeeded(statisticsTotal)) - procCallback.reportInfo(wxToZ(_("Nothing to synchronize according to configuration!"))); //inform about this special case + procCallback.reportInfo(_("Nothing to synchronize according to configuration!")); //inform about this special case std::deque<bool> skipFolderPair(folderCmp.size()); //folder pairs may be skipped after fatal errors were found + + //initialize deletion handling: already required when checking for warnings + std::vector<std::pair<DeletionHandling, DeletionHandling>> delHandler; + for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j) + { + const size_t folderIndex = j - folderCmp.begin(); + const FolderPairSyncCfg& folderPairCfg = syncConfig[folderIndex]; + + delHandler.push_back(std::make_pair(DeletionHandling(folderPairCfg.handleDeletion, + folderPairCfg.custDelFolder, + j->getBaseDir<LEFT_SIDE>(), + procCallback), + + DeletionHandling(folderPairCfg.handleDeletion, + folderPairCfg.custDelFolder, + j->getBaseDir<RIGHT_SIDE>(), + procCallback))); + } + //-------------------some basic checks:------------------------------------------ @@ -1500,6 +1402,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf typedef std::vector<std::pair<Zstring, std::pair<zen::Int64, zen::Int64> > > DirSpaceRequAvailList; //dirname / space required / space available DirSpaceRequAvailList diskSpaceMissing; + typedef std::set<Zstring, LessDependentDirectory> DirRecyclerMissing; + DirRecyclerMissing recyclMissing; //start checking folder pairs for (FolderComparison::const_iterator j = folderCmp.begin(); j != folderCmp.end(); ++j) @@ -1511,6 +1415,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf continue; const FolderPairSyncCfg& folderPairCfg = syncConfig[folderIndex]; + const std::pair<DeletionHandling, DeletionHandling>& delHandlerFp = delHandler[folderIndex]; const SyncStatistics statisticsFolderPair(*j); @@ -1567,14 +1472,6 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf if (statisticsFolderPair.getOverwrite() + statisticsFolderPair.getDelete() > 0) { - //test existence of Recycle Bin - if (folderPairCfg.handleDeletion == zen::MOVE_TO_RECYCLE_BIN && !zen::recycleBinExists()) - { - procCallback.reportFatalError(_("Recycle Bin not yet supported for this system!")); - skipFolderPair[folderIndex] = true; - continue; - } - if (folderPairCfg.handleDeletion == zen::MOVE_TO_CUSTOM_DIRECTORY) { //check if user-defined directory for deletion was specified @@ -1590,13 +1487,13 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //avoid data loss when source directory doesn't (temporarily?) exist anymore AND user chose to ignore errors(else we wouldn't arrive here) if (dataLossPossible(j->getBaseDir<LEFT_SIDE>(), statisticsFolderPair)) { - procCallback.reportFatalError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(j->getBaseDir<LEFT_SIDE>()) + wxT("\"")); + procCallback.reportFatalError(_("Source directory does not exist anymore:") + "\n\"" + j->getBaseDir<LEFT_SIDE>() + "\""); skipFolderPair[folderIndex] = true; continue; } if (dataLossPossible(j->getBaseDir<RIGHT_SIDE>(), statisticsFolderPair)) { - procCallback.reportFatalError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(j->getBaseDir<RIGHT_SIDE>()) + wxT("\"") ); + procCallback.reportFatalError(_("Source directory does not exist anymore:") + "\n\"" + j->getBaseDir<RIGHT_SIDE>() + "\""); skipFolderPair[folderIndex] = true; continue; } @@ -1606,10 +1503,12 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf significantDiff.push_back(std::make_pair(j->getBaseDir<LEFT_SIDE>(), j->getBaseDir<RIGHT_SIDE>())); //check for sufficient free diskspace in left directory - const std::pair<zen::Int64, zen::Int64> spaceNeeded = freeDiskSpaceNeeded(*j, folderPairCfg.handleDeletion, folderPairCfg.custDelFolder); + const std::pair<zen::Int64, zen::Int64> spaceNeeded = DiskSpaceNeeded(*j, + delHandlerFp.first.deletionFreesSpace(), + delHandlerFp.second.deletionFreesSpace()).getSpaceTotal(); wxLongLong freeDiskSpaceLeft; - if (wxGetDiskSpace(zToWx(j->getBaseDir<LEFT_SIDE>()), NULL, &freeDiskSpaceLeft)) + if (wxGetDiskSpace(toWx(j->getBaseDir<LEFT_SIDE>()), NULL, &freeDiskSpaceLeft)) { if (0 < freeDiskSpaceLeft && //zero disk space is either an error or not: in both cases this warning message is obsolete (WebDav seems to report 0) freeDiskSpaceLeft.ToDouble() < to<double>(spaceNeeded.first)) @@ -1618,12 +1517,30 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check for sufficient free diskspace in right directory wxLongLong freeDiskSpaceRight; - if (wxGetDiskSpace(zToWx(j->getBaseDir<RIGHT_SIDE>()), NULL, &freeDiskSpaceRight)) + if (wxGetDiskSpace(toWx(j->getBaseDir<RIGHT_SIDE>()), NULL, &freeDiskSpaceRight)) { if (0 < freeDiskSpaceRight && //zero disk space is either an error or not: in both cases this warning message is obsolete (WebDav seems to report 0) freeDiskSpaceRight.ToDouble() < to<double>(spaceNeeded.second)) diskSpaceMissing.push_back(std::make_pair(j->getBaseDir<RIGHT_SIDE>(), std::make_pair(spaceNeeded.second, freeDiskSpaceRight.ToDouble()))); } + + //windows: check if recycle bin really exists; if not, Windows will silently delete, which is wrong +#ifdef FFS_WIN + if (folderPairCfg.handleDeletion == MOVE_TO_RECYCLE_BIN) + { + if (statisticsFolderPair.getOverwrite<LEFT_SIDE>() + + statisticsFolderPair.getDelete <LEFT_SIDE>() > 0 && + + recycleBinExists(j->getBaseDir<LEFT_SIDE>()) != STATUS_REC_EXISTS) + recyclMissing.insert(j->getBaseDir<LEFT_SIDE>()); + + if (statisticsFolderPair.getOverwrite<RIGHT_SIDE>() + + statisticsFolderPair.getDelete <RIGHT_SIDE>() > 0 && + + recycleBinExists(j->getBaseDir<RIGHT_SIDE>()) != STATUS_REC_EXISTS) + recyclMissing.insert(j->getBaseDir<RIGHT_SIDE>()); + } +#endif } //check if unresolved conflicts exist @@ -1639,7 +1556,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf wxString conflictDescription = i->second; //conflictDescription.Replace(wxT("\n"), wxT(" ")); //remove line-breaks - warningMessage += wxString(wxT("\"")) + zToWx(i->first) + wxT("\": ") + conflictDescription + wxT("\n\n"); + warningMessage += wxString(wxT("\"")) + i->first + "\": " + conflictDescription + "\n\n"; } if (statisticsTotal.getConflict() > static_cast<int>(firstConflicts.size())) @@ -1658,8 +1575,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf for (DirPairList::const_iterator i = significantDiff.begin(); i != significantDiff.end(); ++i) warningMessage += wxString(wxT("\n\n")) + - zToWx(i->first) + wxT(" <-> ") + wxT("\n") + - zToWx(i->second); + i->first + " <-> " + "\n" + + i->second; warningMessage += wxString(wxT("\n\n")) +_("More than 50% of the total number of files will be copied or deleted!"); procCallback.reportWarning(warningMessage, m_warnings.warningSignificantDifference); @@ -1671,9 +1588,9 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf { wxString warningMessage = _("Not enough free disk space available in:"); - for (DirSpaceRequAvailList::const_iterator i = diskSpaceMissing.begin(); i != diskSpaceMissing.end(); ++i) + for (auto i = diskSpaceMissing.begin(); i != diskSpaceMissing.end(); ++i) warningMessage += wxString(wxT("\n\n")) + - wxT("\"") + zToWx(i->first) + wxT("\"\n") + + "\"" + i->first + "\"\n" + _("Free disk space required:") + wxT(" ") + formatFilesizeToShortString(to<zen::UInt64>(i->second.first)) + wxT("\n") + _("Free disk space available:") + wxT(" ") + formatFilesizeToShortString(to<zen::UInt64>(i->second.second)); @@ -1681,6 +1598,20 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf } + //windows: check if recycle bin really exists; if not, Windows will silently delete, which is wrong +#ifdef FFS_WIN + if (!recyclMissing.empty()) + { + wxString warningMessage = _("Recycle Bin is not available for the following paths! Files will be deleted permanently instead:"); + warningMessage += L"\n"; + + std::for_each(recyclMissing.begin(), recyclMissing.end(), + [&](const Zstring& path) { warningMessage += L"\n" + toWx(path); }); + + procCallback.reportWarning(warningMessage, m_warnings.warningRecyclerMissing); + } +#endif + //check if folders are used by multiple pairs in read/write access std::vector<Zstring> conflictDirs; for (DirWriteMap::const_iterator i = dirWriteCount.begin(); i != dirWriteCount.end(); ++i) @@ -1693,30 +1624,15 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf wxString warningMessage = wxString(_("A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!")) + wxT("\n"); for (std::vector<Zstring>::const_iterator i = conflictDirs.begin(); i != conflictDirs.end(); ++i) warningMessage += wxString(wxT("\n")) + - wxT("\"") + zToWx(*i) + wxT("\""); + "\"" + *i + "\""; procCallback.reportWarning(warningMessage, m_warnings.warningMultiFolderWriteAccess); } //-------------------end of basic checks------------------------------------------ #ifdef FFS_WIN - struct ShadowCallback : public shadow::WaitingForShadow - { - ShadowCallback(ProcessCallback& updater) : procCallback_(updater) {} - virtual void requestUiRefresh() //allowed to throw exceptions - { - procCallback_.requestUiRefresh(); - } - virtual void reportInfo(const Zstring& text) - { - procCallback_.reportInfo(text); - } - private: - ProcessCallback& procCallback_; - } shadowCb(procCallback); - //shadow copy buffer: per sync-instance, not folder pair - boost::scoped_ptr<shadow::ShadowCopy> shadowCopyHandler(copyLockedFiles_ ? new shadow::ShadowCopy(&shadowCb) : NULL); + boost::scoped_ptr<shadow::ShadowCopy> shadowCopyHandler(copyLockedFiles_ ? new shadow::ShadowCopy : NULL); #endif try @@ -1726,12 +1642,12 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf (void)dummy; //loop through all directory pairs - assert(syncConfig.size() == folderCmp.size()); for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j) { const size_t folderIndex = j - folderCmp.begin(); const FolderPairSyncCfg& folderPairCfg = syncConfig[folderIndex]; + std::pair<DeletionHandling, DeletionHandling>& delHandlerFp = delHandler[folderIndex]; if (skipFolderPair[folderIndex]) //folder pairs may be skipped after fatal errors were found continue; @@ -1742,46 +1658,37 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //------------------------------------------------------------------------------------------ //info about folder pair to be processed (useful for logfile) - wxString left = wxString(_("Left")) + wxT(": "); - wxString right = wxString(_("Right")) + wxT(": "); + std::wstring left = _("Left") + ": "; + std::wstring right = _("Right") + ": "; makeSameLength(left, right); - const wxString statusTxt = wxString(_("Processing folder pair:")) + wxT(" \n") + - wxT("\t") + left + wxT("\"") + zToWx(j->getBaseDir<LEFT_SIDE>()) + wxT("\"")+ wxT(" \n") + - wxT("\t") + right + wxT("\"") + zToWx(j->getBaseDir<RIGHT_SIDE>()) + wxT("\""); - procCallback.reportInfo(wxToZ(statusTxt)); + const std::wstring statusTxt = _("Processing folder pair:") + " \n" + + "\t" + left + "\"" + j->getBaseDir<LEFT_SIDE>() + "\"" + " \n" + + "\t" + right + "\"" + j->getBaseDir<RIGHT_SIDE>() + "\""; + procCallback.reportInfo(statusTxt); //------------------------------------------------------------------------------------------ //create base directories first (if not yet existing) -> no symlink or attribute copying! -> single error message instead of one per file (e.g. unplugged network drive) - const Zstring dirnameLeft = j->getBaseDir<LEFT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring dirnameLeft = j->getBaseDir<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR); if (!dirnameLeft.empty() && !zen::dirExists(dirnameLeft)) { if (!tryReportingError(procCallback, boost::bind(zen::createDirectory, boost::cref(dirnameLeft)))) //may throw in error-callback! continue; //skip this folder pair } - const Zstring dirnameRight = j->getBaseDir<RIGHT_SIDE>().BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring dirnameRight = j->getBaseDir<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR); if (!dirnameRight.empty() && !zen::dirExists(dirnameRight)) { if (!tryReportingError(procCallback, boost::bind(zen::createDirectory, boost::cref(dirnameRight)))) //may throw in error-callback! continue; //skip this folder pair } //------------------------------------------------------------------------------------------ - - //generate name of alternate deletion directory (unique for session AND folder pair) - const DeletionHandling currentDelHandling( - folderPairCfg.handleDeletion, - folderPairCfg.custDelFolder, - j->getBaseDir<LEFT_SIDE>(), j->getBaseDir<RIGHT_SIDE>(), - procCallback); - - //------------------------------------------------------------------------------------------ //execute synchronization recursively //update synchronization database (automatic sync only) - std::auto_ptr<EnforceUpdateDatabase> dummyUpdateDb; + std::auto_ptr<EnforceUpdateDatabase> guardUpdateDb; if (folderPairCfg.inAutomaticMode) - dummyUpdateDb.reset(new EnforceUpdateDatabase(*j, procCallback)); + guardUpdateDb.reset(new EnforceUpdateDatabase(*j)); //enforce removal of invalid entries (where element on both sides is empty) struct RemoveInvalid @@ -1799,19 +1706,21 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf #ifdef FFS_WIN shadowCopyHandler.get(), #endif - currentDelHandling); - - //loop through all files twice; reason: first delete files (or overwrite big ones with smaller ones), then copy rest - syncFP.startSync<true>(*j); - syncFP.startSync<false>(*j); + delHandlerFp.first, delHandlerFp.second); + syncFP.startSync(*j); //(try to gracefully) cleanup temporary folders (Recycle bin optimization) -> will be done in ~DeletionHandling anyway... - currentDelHandling.tryCleanup(); //show error dialog if necessary + tryReportingError(procCallback, [&]() { delHandlerFp.first .tryCleanup(); }); //show error dialog if necessary + tryReportingError(procCallback, [&]() { delHandlerFp.second.tryCleanup(); }); // //(try to gracefully) write database file (will be done in ~EnforceUpdateDatabase anyway...) - if (dummyUpdateDb.get()) - dummyUpdateDb->tryWriteDB(); + if (guardUpdateDb.get()) + { + procCallback.reportInfo(_("Generating database...")); + procCallback.forceUiRefresh(); + tryReportingError(procCallback, [&]() { guardUpdateDb->tryWriteDB(); }); + } } } catch (const std::exception& e) @@ -1828,74 +1737,46 @@ template <class DelTargetCommand> class WhileCopying : public zen::CallbackCopyFile //callback functionality { public: - WhileCopying(zen::Int64& bytesTransferredLast, + WhileCopying(UInt64& bytesReported, ProcessCallback& statusHandler, const DelTargetCommand& cmd) : - bytesTransferredLast_(bytesTransferredLast), + bytesReported_(bytesReported), statusHandler_(statusHandler), cmd_(cmd) {} virtual void deleteTargetFile(const Zstring& targetFile) { cmd_(); } - virtual Response updateCopyStatus(zen::UInt64 totalBytesTransferred) + virtual void updateCopyStatus(UInt64 totalBytesTransferred) { - const zen::Int64 totalBytes = to<zen::Int64>(totalBytesTransferred); //convert to signed - //inform about the (differential) processed amount of data - statusHandler_.updateProcessedData(0, totalBytes - bytesTransferredLast_); - bytesTransferredLast_ = totalBytes; + statusHandler_.updateProcessedData(0, to<Int64>(totalBytesTransferred) - to<Int64>(bytesReported_)); //throw()! -> this ensures client and service provider are in sync! + bytesReported_ = totalBytesTransferred; // -#ifdef FFS_WIN - statusHandler_.requestUiRefresh(false); //don't allow throwing exception within this call: windows copying callback can't handle this - if (statusHandler_.abortIsRequested()) - return CallbackCopyFile::CANCEL; -#elif defined FFS_LINUX - statusHandler_.requestUiRefresh(); //exceptions may be thrown here! -#endif - return CallbackCopyFile::CONTINUE; + statusHandler_.requestUiRefresh(); //may throw } private: - zen::Int64& bytesTransferredLast_; - ProcessCallback& statusHandler_; + UInt64& bytesReported_; + ProcessCallback& statusHandler_; DelTargetCommand cmd_; }; -class CleanUpStats //lambdas coming soon... unfortunately Loki::ScopeGuard is no option because of lazy function argument evaluation (-1 * ...) -{ - bool dismissed; - ProcessCallback& procCallback_; - zen::Int64 bytesTransferred_; - -public: - CleanUpStats(ProcessCallback& procCallback, zen::Int64 bytesTransferred) : dismissed(false), procCallback_(procCallback), bytesTransferred_(bytesTransferred) {} - ~CleanUpStats() - { - if (!dismissed) - try - { - procCallback_.updateProcessedData(0, bytesTransferred_ * -1); //throw ? - } - catch (...) {} - } - void dismiss() { dismissed = true; } -}; - - -//copy file while executing procCallback->requestUiRefresh() calls +//copy file while refreshing UI template <class DelTargetCommand> -void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstring& target, const DelTargetCommand& cmd, zen::UInt64 totalBytesToCpy, int recursionLvl) const +void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstring& target, const DelTargetCommand& cmd, UInt64 totalBytesToCpy, int recursionLvl) const { const int exceptionPaths = 2; + //start of (possibly) long-running copy process: ensure status updates are performed regularly + UInt64 bytesReported; + + //in error situation: undo communication of processed amount of data + Loki::ScopeGuard guardStatistics = Loki::MakeGuard([&]() { procCallback_.updateProcessedData(0, -1 * to<Int64>(bytesReported)); }); + try { - //start of (possibly) long-running copy process: ensure status updates are performed regularly - zen::Int64 totalBytesTransferred; - CleanUpStats dummy(procCallback_, totalBytesTransferred); //error situation: undo communication of processed amount of data - - WhileCopying<DelTargetCommand> callback(totalBytesTransferred, procCallback_, cmd); + WhileCopying<DelTargetCommand> callback(bytesReported, procCallback_, cmd); zen::copyFile(source, //type File implicitly means symlinks need to be dereferenced! target, @@ -1903,8 +1784,8 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin &callback); //throw (FileError, ErrorFileLocked); //inform about the (remaining) processed amount of data - dummy.dismiss(); - procCallback_.updateProcessedData(0, to<zen::Int64>(totalBytesToCpy) - totalBytesTransferred); + procCallback_.updateProcessedData(0, to<Int64>(totalBytesToCpy) - to<Int64>(bytesReported)); + bytesReported = totalBytesToCpy; } #ifdef FFS_WIN catch (ErrorFileLocked&) @@ -1922,10 +1803,9 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin } catch (const FileError& e) { - wxString errorMsg = _("Error copying locked file %x!"); - errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(source) + wxT("\"")); - errorMsg += wxT("\n\n") + e.msg(); - throw FileError(errorMsg); + std::wstring errorMsg = _("Error copying locked file %x!"); + replace(errorMsg, L"%x", std::wstring(L"\"") + source + "\""); + throw FileError(errorMsg + "\n\n" + e.msg()); } //now try again @@ -1938,8 +1818,8 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin //create folders "first" (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080) //using optimistic strategy: assume everything goes well, but cover up on error -> minimize file accesses - const Zstring targetDir = target.BeforeLast(common::FILE_NAME_SEPARATOR); - const Zstring templateDir = source.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring targetDir = target.BeforeLast(FILE_NAME_SEPARATOR); + const Zstring templateDir = source.BeforeLast(FILE_NAME_SEPARATOR); if (!targetDir.empty()) { @@ -1960,6 +1840,8 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin if (verifyCopiedFiles_) //verify if data was copied correctly verifyFileCopy(source, target); //throw (FileError) + + guardStatistics.Dismiss(); } @@ -1984,8 +1866,8 @@ void SynchronizeFolderPair::copySymlink(const Zstring& source, const Zstring& ta //create folders "first" (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080) //using optimistic strategy: assume everything goes well, but cover up on error -> minimize file accesses - const Zstring targetDir = target.BeforeLast(common::FILE_NAME_SEPARATOR); - const Zstring templateDir = source.BeforeLast(common::FILE_NAME_SEPARATOR); + const Zstring targetDir = target.BeforeLast(FILE_NAME_SEPARATOR); + const Zstring templateDir = source.BeforeLast(FILE_NAME_SEPARATOR); if (!targetDir.empty() && !zen::dirExists(targetDir)) { @@ -2008,14 +1890,16 @@ void SynchronizeFolderPair::copySymlink(const Zstring& source, const Zstring& ta template <zen::SelectedSide side> void SynchronizeFolderPair::deleteSymlink(const SymLinkMapping& linkObj) const { + const DeletionHandling& delHandling = side == LEFT_SIDE ? delHandlingLeft_ : delHandlingRight_; + switch (linkObj.getLinkType<side>()) { case LinkDescriptor::TYPE_DIR: - delHandling_.removeFolder<side>(linkObj); //throw (FileError) + delHandling.removeFolder(linkObj.getObjRelativeName()); //throw (FileError) break; case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link - delHandling_.removeFile<side>(linkObj); //throw (FileError) + delHandling.removeFile(linkObj.getObjRelativeName()); //throw (FileError) break; } } @@ -2031,7 +1915,7 @@ struct VerifyCallback }; -void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback* callback) // throw (FileError) +void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback& callback) // throw (FileError) { static std::vector<char> memory1(1024 * 1024); //1024 kb seems to be a reasonable buffer size static std::vector<char> memory2(1024 * 1024); @@ -2042,7 +1926,7 @@ void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback* c wxFile file1(::open(source.c_str(), O_RDONLY)); //utilize UTF-8 filename #endif if (!file1.IsOpened()) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(source) + wxT("\"")); + throw FileError(_("Error opening file:") + " \"" + source + "\""); #ifdef FFS_WIN wxFile file2(zen::applyLongPathPrefix(target).c_str(), wxFile::read); //don't use buffered file input for verification! @@ -2050,31 +1934,27 @@ void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback* c wxFile file2(::open(target.c_str(), O_RDONLY)); //utilize UTF-8 filename #endif if (!file2.IsOpened()) //NO cleanup necessary for (wxFile) file1 - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(target) + wxT("\"")); + throw FileError(_("Error opening file:") + " \"" + target + "\""); do { const size_t length1 = file1.Read(&memory1[0], memory1.size()); - if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(source) + wxT("\"")); - callback->updateStatus(); //send progress updates + if (file1.Error()) + throw FileError(_("Error reading file:") + " \"" + source + "\""); + callback.updateStatus(); //send progress updates const size_t length2 = file2.Read(&memory2[0], memory2.size()); - if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(target) + wxT("\"")); - callback->updateStatus(); //send progress updates + if (file2.Error()) + throw FileError(_("Error reading file:") + " \"" + target + "\""); + callback.updateStatus(); //send progress updates if (length1 != length2 || ::memcmp(&memory1[0], &memory2[0], length1) != 0) - { - const wxString errorMsg = wxString(_("Data verification error: Source and target file have different content!")) + wxT("\n"); - throw FileError(errorMsg + wxT("\"") + zToWx(source) + wxT("\" -> \n\"") + zToWx(target) + wxT("\"")); - } + throw FileError(_("Data verification error: Source and target file have different content!") + "\n" + "\"" + source + "\" -> \n\"" + target + "\""); } while (!file1.Eof()); if (!file2.Eof()) - { - const wxString errorMsg = wxString(_("Data verification error: Source and target file have different content!")) + wxT("\n"); - throw FileError(errorMsg + wxT("\"") + zToWx(source) + wxT("\" -> \n\"") + zToWx(target) + wxT("\"")); - } + throw FileError(_("Data verification error: Source and target file have different content!") + "\n" + "\"" + source + "\" -> \n\"" + target + "\""); } @@ -2083,10 +1963,7 @@ class VerifyStatusUpdater : public VerifyCallback public: VerifyStatusUpdater(ProcessCallback& statusHandler) : statusHandler_(statusHandler) {} - virtual void updateStatus() - { - statusHandler_.requestUiRefresh(); //trigger display refresh - } + virtual void updateStatus() { statusHandler_.requestUiRefresh(); } //trigger display refresh private: ProcessCallback& statusHandler_; @@ -2097,10 +1974,9 @@ void SynchronizeFolderPair::verifyFileCopy(const Zstring& source, const Zstring& { Zstring statusText = txtVerifying; statusText.Replace(Zstr("%x"), target, false); - procCallback_.reportInfo(statusText); - procCallback_.requestUiRefresh(); //trigger display refresh + procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText)); VerifyStatusUpdater callback(procCallback_); - tryReportingError(procCallback_, boost::bind(&::verifyFiles, boost::ref(source), boost::ref(target), &callback)); + tryReportingError(procCallback_, [&]() { ::verifyFiles(source, target, callback);}); } diff --git a/ui/batch_config.cpp b/ui/batch_config.cpp index 557cb229..c6aa4df7 100644 --- a/ui/batch_config.cpp +++ b/ui/batch_config.cpp @@ -15,7 +15,7 @@ #include "gui_generated.h" #include <wx/dnd.h> #include <wx/msgdlg.h> -//#include "../shared/util.h" +#include "../shared/custom_button.h" #include "../shared/wx_choice_enum.h" #include "../shared/mouse_move_dlg.h" @@ -47,7 +47,7 @@ private: void OnGlobalFilterOpenContext(wxCommandEvent& event); void OnGlobalFilterRemConfirm(wxCommandEvent& event); - virtual void OnCheckSilent( wxCommandEvent& event); + virtual void OnCheckSaveLog( wxCommandEvent& event); virtual void OnChangeMaxLogCountTxt(wxCommandEvent& event); virtual void OnClose( wxCloseEvent& event); virtual void OnCancel( wxCommandEvent& event); @@ -70,14 +70,15 @@ private: //error handling //xmlAccess::OnError getSelectionHandleError() const; -> obsolete, use getEnumVal() - void setSelectionHandleError(const xmlAccess::OnError value); + void setSelectionHandleError(xmlAccess::OnError value); void OnChangeErrorHandling(wxCommandEvent& event); bool saveBatchFile(const wxString& filename); void loadBatchFile(const wxString& filename); - void loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg); + void loadBatchFile(const std::vector<wxString>& filenames); - xmlAccess::XmlBatchConfig getCurrentConfiguration() const; + void setConfig(const xmlAccess::XmlBatchConfig& batchCfg); + xmlAccess::XmlBatchConfig getConfig() const; std::shared_ptr<DirectoryPairBatchFirst> firstFolderPair; //always bound!!! std::vector<DirectoryPairBatch*> additionalFolderPairs; @@ -127,7 +128,7 @@ private: virtual MainConfiguration getMainConfig() const { - return batchDlg.getCurrentConfiguration().mainCfg; + return batchDlg.getConfig().mainCfg; } virtual void OnAltSyncCfgChange() @@ -210,7 +211,7 @@ BatchDialog::BatchDialog(wxWindow* window, const xmlAccess::XmlBatchConfig& batc BatchDlgGenerated(window) { init(); - loadBatchCfg(batchCfg); + setConfig(batchCfg); } @@ -253,7 +254,7 @@ void BatchDialog::init() setupFileDrop(*this); Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(BatchDialog::OnFilesDropped), NULL, this); - logfileDir.reset(new DirectoryName(*m_panelLogging, *m_dirPickerLogfileDir, *m_textCtrlLogfileDir, sbSizerLogfileDir)); + logfileDir.reset(new DirectoryName(*m_panelBatchSettings, *m_dirPickerLogfileDir, *m_textCtrlLogfileDir)); //set icons for this dialog m_bpButtonAddPair->SetBitmapLabel(GlobalResources::instance().getImage(wxT("addFolderPair"))); @@ -264,16 +265,17 @@ void BatchDialog::init() //------------------- error handling -------------------------- -void BatchDialog::setSelectionHandleError(const xmlAccess::OnError value) +void BatchDialog::setSelectionHandleError(xmlAccess::OnError value) { - if (m_checkBoxSilent->GetValue()) - setEnumVal(enumDescrMap, *m_choiceHandleError, value); - else - { - EnumDescrList<xmlAccess::OnError> tmp(enumDescrMap); - tmp.descrList.pop_back(); //remove "Exit instantly" -> this option shall be available for silent mode only! - setEnumVal(tmp, *m_choiceHandleError, value); - } + // if (m_checkBoxSilent->GetValue()) + setEnumVal(enumDescrMap, *m_choiceHandleError, value); + /* else + { + EnumDescrList<xmlAccess::OnError> tmp(enumDescrMap); + tmp.descrList.pop_back(); //remove "Exit instantly" -> this option shall be available for silent mode only! + setEnumVal(tmp, *m_choiceHandleError, value); + } + */ } void BatchDialog::OnChangeErrorHandling(wxCommandEvent& event) @@ -284,13 +286,11 @@ void BatchDialog::OnChangeErrorHandling(wxCommandEvent& event) void BatchDialog::OnCmpSettings(wxCommandEvent& event) { - //show window right next to the compare-config button - wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); - windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; + //wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); + //windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; - if (zen::showCompareCfgDialog(windowPos, - localBatchCfg.mainCfg.compareVar, + if (zen::showCompareCfgDialog(localBatchCfg.mainCfg.compareVar, localBatchCfg.mainCfg.handleSymlinks) == ReturnSmallDlg::BUTTON_OKAY) { updateGui(); @@ -323,12 +323,11 @@ void BatchDialog::OnConfigureFilter(wxCommandEvent& event) void BatchDialog::updateGui() //re-evaluate gui after config changes { - xmlAccess::XmlBatchConfig cfg = getCurrentConfiguration(); + xmlAccess::XmlBatchConfig cfg = getConfig(); - showNotebookpage(m_panelLogging, _("Logging"), cfg.silent); + //showNotebookpage(m_panelLogging, _("Logging"), cfg.silent); - m_textCtrlLogfileDir ->Enable(cfg.logFileCountMax > 0); - m_dirPickerLogfileDir->Enable(cfg.logFileCountMax > 0); + m_panelLogfile->Enable(cfg.logFileCountMax > 0); //update compare variant name m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(cfg.mainCfg.compareVar) + wxT(")")); @@ -339,12 +338,12 @@ void BatchDialog::updateGui() //re-evaluate gui after config changes //set filter icon if (isNullFilter(cfg.mainCfg.globalFilter)) { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOff"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOff"))); m_bpButtonFilter->SetToolTip(_("No filter selected")); } else { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOn"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOn"))); m_bpButtonFilter->SetToolTip(_("Filter is active")); } @@ -354,13 +353,14 @@ void BatchDialog::updateGui() //re-evaluate gui after config changes void BatchDialog::OnGlobalFilterOpenContext(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BatchDialog::OnGlobalFilterRemConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BatchDialog::OnGlobalFilterRemConfirm), NULL, this); if (isNullFilter(localBatchCfg.mainCfg.globalFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway PopupMenu(contextMenu.get()); //show context menu } @@ -373,12 +373,12 @@ void BatchDialog::OnGlobalFilterRemConfirm(wxCommandEvent& event) } -void BatchDialog::OnCheckSilent(wxCommandEvent& event) +void BatchDialog::OnCheckSaveLog(wxCommandEvent& event) { updateGui(); //reset error handling depending on "m_checkBoxSilent" - setSelectionHandleError(getEnumVal(enumDescrMap, *m_choiceHandleError)); + //setSelectionHandleError(getEnumVal(enumDescrMap, *m_choiceHandleError)); } @@ -393,37 +393,14 @@ void BatchDialog::OnFilesDropped(FFSFileDropEvent& event) if (event.getFiles().empty()) return; - std::vector<wxString> fileList = event.getFiles(); + const std::vector<wxString>& fileList = event.getFiles(); switch (xmlAccess::getMergeType(fileList)) //throw () { case xmlAccess::MERGE_BATCH: case xmlAccess::MERGE_GUI: case xmlAccess::MERGE_GUI_BATCH: - if (fileList.size() == 1) - { - loadBatchFile(fileList[0]); - return; - } - else - { - xmlAccess::XmlBatchConfig batchCfg; - try - { - convertConfig(fileList, batchCfg); //throw (xmlAccess::FfsXmlError) - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return; - } - } - loadBatchCfg(batchCfg); - } + loadBatchFile(fileList); break; case xmlAccess::MERGE_OTHER: @@ -494,19 +471,15 @@ void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) defaultFileName.Replace(wxT(".ffs_gui"), wxT(".ffs_batch"), false); - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("FreeFileSync batch file")) + wxT(" (*.ffs_batch)|*.ffs_batch"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + wxEmptyString, + defaultFileName, + wxString(_("FreeFileSync batch file")) + wxT(" (*.ffs_batch)|*.ffs_batch"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { const wxString newFileName = filePicker.GetPath(); - if (zen::fileExists(wxToZ(newFileName))) - { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - { - OnSaveBatchJob(event); //retry - return; - } - } //create batch file if (saveBatchFile(newFileName)) @@ -517,9 +490,20 @@ void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) void BatchDialog::OnLoadBatchJob(wxCommandEvent& event) { - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, wxEmptyString, wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_batch;*.ffs_gui)|*.ffs_batch;*.ffs_gui"), wxFD_OPEN); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + beforeLast(proposedBatchFileName, FILE_NAME_SEPARATOR), //set default dir: empty string if "currentConfigFileName" is empty or has no path separator + wxEmptyString, + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_batch;*.ffs_gui)|*.ffs_batch;*.ffs_gui"), + wxFD_OPEN | wxFD_MULTIPLE); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) - loadBatchFile(filePicker.GetPath()); + { + wxArrayString tmp; + filePicker.GetPaths(tmp); + std::vector<wxString> fileNames(tmp.begin(), tmp.end()); + + loadBatchFile(fileNames); + } } @@ -527,44 +511,16 @@ void BatchDialog::OnLoadBatchJob(wxCommandEvent& event) inline FolderPairEnh getEnhancedPair(const DirectoryPairBatch* panel) { - return FolderPairEnh(wxToZ(panel->getLeftDir()), - wxToZ(panel->getRightDir()), + return FolderPairEnh(toZ(panel->getLeftDir()), + toZ(panel->getRightDir()), panel->getAltSyncConfig(), panel->getAltFilterConfig()); } -xmlAccess::XmlBatchConfig BatchDialog::getCurrentConfiguration() const -{ - xmlAccess::XmlBatchConfig batchCfg = localBatchCfg; - - //load parameter with ownership within wxWidgets controls... - - //first folder pair - batchCfg.mainCfg.firstPair = FolderPairEnh(wxToZ(firstFolderPair->getLeftDir()), - wxToZ(firstFolderPair->getRightDir()), - firstFolderPair->getAltSyncConfig(), - firstFolderPair->getAltFilterConfig()); - - //add additional pairs - batchCfg.mainCfg.additionalPairs.clear(); - std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(), - std::back_inserter(batchCfg.mainCfg.additionalPairs), getEnhancedPair); - - - //load structure with batch settings "batchCfg" - batchCfg.silent = m_checkBoxSilent->GetValue(); - batchCfg.logFileDirectory = logfileDir->getName(); - batchCfg.logFileCountMax = m_spinCtrlLogCountMax->GetValue(); - batchCfg.handleError = getEnumVal(enumDescrMap, *m_choiceHandleError); - - return batchCfg; -} - - bool BatchDialog::saveBatchFile(const wxString& filename) { - const xmlAccess::XmlBatchConfig batchCfg = getCurrentConfiguration(); + const xmlAccess::XmlBatchConfig batchCfg = getConfig(); //write config to XML try @@ -577,7 +533,7 @@ bool BatchDialog::saveBatchFile(const wxString& filename) return false; } - SetTitle(wxString(_("Create a batch job")) + wxT(" - ") + filename); + SetTitle(filename); proposedBatchFileName = filename; //may be used on next save return true; @@ -586,14 +542,22 @@ bool BatchDialog::saveBatchFile(const wxString& filename) void BatchDialog::loadBatchFile(const wxString& filename) { + std::vector<wxString> filenames; + filenames.push_back(filename); + loadBatchFile(filenames); +} + + +void BatchDialog::loadBatchFile(const std::vector<wxString>& filenames) +{ + if (filenames.empty()) + return; + //load XML settings xmlAccess::XmlBatchConfig batchCfg; //structure to receive gui settings try { //open a *.ffs_gui or *.ffs_batch file! - std::vector<wxString> filenames; - filenames.push_back(filename); - xmlAccess::convertConfig(filenames, batchCfg); //throw (xmlAccess::FfsXmlError) //xmlAccess::readConfig(filename, batchCfg); @@ -609,13 +573,20 @@ void BatchDialog::loadBatchFile(const wxString& filename) } } - SetTitle(wxString(_("Create a batch job")) + wxT(" - ") + filename); - proposedBatchFileName = filename; //may be used on next save - this->loadBatchCfg(batchCfg); + const wxString activeFile = filenames.size() == 1 ? filenames[0] : wxString(); + + if (activeFile.empty()) + SetTitle(_("Create a batch job")); + else + SetTitle(activeFile); + + proposedBatchFileName = activeFile; //may be used on next save + + setConfig(batchCfg); } -void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) +void BatchDialog::setConfig(const xmlAccess::XmlBatchConfig& batchCfg) { wxWindowUpdateLocker dummy(this); //avoid display distortion @@ -623,6 +594,7 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) localBatchCfg = batchCfg; m_checkBoxSilent->SetValue(batchCfg.silent); + //error handling is dependent from m_checkBoxSilent! /|\ \|/ setSelectionHandleError(batchCfg.handleError); @@ -630,8 +602,8 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) m_spinCtrlLogCountMax->SetValue(static_cast<int>(batchCfg.logFileCountMax)); //attention: this one emits a "change value" event!! => updateGui() called implicitly! //set first folder pair - firstFolderPair->setValues(zToWx(batchCfg.mainCfg.firstPair.leftDirectory), - zToWx(batchCfg.mainCfg.firstPair.rightDirectory), + firstFolderPair->setValues(toWx(batchCfg.mainCfg.firstPair.leftDirectory), + toWx(batchCfg.mainCfg.firstPair.rightDirectory), batchCfg.mainCfg.firstPair.altSyncConfig, batchCfg.mainCfg.firstPair.localFilter); @@ -649,19 +621,47 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) } +xmlAccess::XmlBatchConfig BatchDialog::getConfig() const +{ + xmlAccess::XmlBatchConfig batchCfg = localBatchCfg; + + //load parameter with ownership within wxWidgets controls... + + //first folder pair + batchCfg.mainCfg.firstPair = FolderPairEnh(toZ(firstFolderPair->getLeftDir()), + toZ(firstFolderPair->getRightDir()), + firstFolderPair->getAltSyncConfig(), + firstFolderPair->getAltFilterConfig()); + + //add additional pairs + batchCfg.mainCfg.additionalPairs.clear(); + std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(), + std::back_inserter(batchCfg.mainCfg.additionalPairs), getEnhancedPair); + + + //load structure with batch settings "batchCfg" + batchCfg.silent = m_checkBoxSilent->GetValue(); + batchCfg.logFileDirectory = logfileDir->getName(); + batchCfg.logFileCountMax = m_spinCtrlLogCountMax->GetValue(); + batchCfg.handleError = getEnumVal(enumDescrMap, *m_choiceHandleError); + + return batchCfg; +} + + void BatchDialog::OnAddFolderPair(wxCommandEvent& event) { wxWindowUpdateLocker dummy(this); //avoid display distortion std::vector<FolderPairEnh> newPairs; - newPairs.push_back(getCurrentConfiguration().mainCfg.firstPair); + newPairs.push_back(getConfig().mainCfg.firstPair); addFolderPair(newPairs, true); //add pair in front of additonal pairs //clear first pair const FolderPairEnh cfgEmpty; - firstFolderPair->setValues(zToWx(cfgEmpty.leftDirectory), - zToWx(cfgEmpty.rightDirectory), + firstFolderPair->setValues(toWx(cfgEmpty.leftDirectory), + toWx(cfgEmpty.rightDirectory), cfgEmpty.altSyncConfig, cfgEmpty.localFilter); } @@ -690,8 +690,8 @@ void BatchDialog::OnRemoveTopFolderPair(wxCommandEvent& event) const FolderPairEnh cfgSecond = getEnhancedPair(additionalFolderPairs[0]); //reset first pair - firstFolderPair->setValues(zToWx(cfgSecond.leftDirectory), - zToWx(cfgSecond.rightDirectory), + firstFolderPair->setValues(toWx(cfgSecond.leftDirectory), + toWx(cfgSecond.rightDirectory), cfgSecond.altSyncConfig, cfgSecond.localFilter); @@ -723,10 +723,11 @@ void BatchDialog::updateGuiForFolderPair() } //update controls + const int maxAddFolderPairsVisible = 2; int pairHeight = sbSizerMainPair->GetSize().GetHeight(); //respect height of main pair if (additionalFolderPairs.size() > 0) - pairHeight += std::min<double>(1.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there + pairHeight += std::min<double>(maxAddFolderPairsVisible + 0.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there additionalFolderPairs[0]->GetSize().GetHeight(); m_scrolledWindow6->SetMinSize(wxSize( -1, pairHeight)); @@ -771,8 +772,8 @@ void BatchDialog::addFolderPair(const std::vector<zen::FolderPairEnh>& newPairs, newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BatchDialog::OnRemoveFolderPair), NULL, this ); //set alternate configuration - newPair->setValues(zToWx(i->leftDirectory), - zToWx(i->rightDirectory), + newPair->setValues(toWx(i->leftDirectory), + toWx(i->rightDirectory), i->altSyncConfig, i->localFilter); } diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp index 4b4740f9..2cfd43cb 100644 --- a/ui/batch_status_handler.cpp +++ b/ui/batch_status_handler.cpp @@ -41,7 +41,7 @@ public: return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); //DON'T traverse into subdirs } - virtual void onError(const wxString& errorText) {} //errors are not really critical in this context + virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } //errors are not really critical in this context private: const Zstring prefix_; @@ -68,11 +68,11 @@ public: logFile.Open(logfileName, wxT("w")); if (!logFile.IsOpened()) - throw FileError(wxString(_("Unable to create logfile!")) + wxT("\"") + logfileName + wxT("\"")); + throw FileError(_("Unable to create logfile!") + "\"" + logfileName.c_str() + "\""); //write header - wxString headerLine = wxString(wxT("FreeFileSync - ")) + _("Batch execution") + - wxT(" (") + _("Date") + wxT(": ") + wxDateTime::Now().FormatDate() + wxT(")"); //"Date" is used at other places, too + wxString headerLine = L"FreeFileSync - " + _("Batch execution") + + " (" + _("Date") + ": " + wxDateTime::Now().FormatDate() + ")"; //"Date" is used at other places, too logFile.Write(headerLine + wxChar('\n')); logFile.Write(wxString().Pad(headerLine.Len(), wxChar('-')) + wxChar('\n') + wxChar('\n')); @@ -110,9 +110,9 @@ public: void limitLogfileCount(size_t maxCount) const { std::vector<Zstring> logFiles; - FindLogfiles traverseCallback(wxToZ(jobName_), logFiles); + FindLogfiles traverseCallback(toZ(jobName_), logFiles); - traverseFolder(wxToZ(logfileName).BeforeLast(common::FILE_NAME_SEPARATOR), //throw(); + traverseFolder(beforeLast(toZ(logfileName), FILE_NAME_SEPARATOR), //throw(); false, //don't follow symlinks traverseCallback); @@ -131,8 +131,8 @@ private: //create logfile directory Zstring logfileDir = logfileDirectory.empty() ? - wxToZ(zen::getConfigDir() + wxT("Logs")) : - zen::getFormattedDirectoryName(wxToZ(logfileDirectory)); + toZ(zen::getConfigDir() + wxT("Logs")) : + zen::getFormattedDirectoryName(toZ(logfileDirectory)); if (!zen::dirExists(logfileDir)) zen::createDirectory(logfileDir); //create recursively if necessary: may throw (FileError&) @@ -141,7 +141,7 @@ private: if (!logfileDir.EndsWith(FILE_NAME_SEPARATOR)) logfileDir += FILE_NAME_SEPARATOR; - wxString logfileName = zToWx(logfileDir); + wxString logfileName = toWx(logfileDir); //add prefix logfileName += jobName + wxT(" "); @@ -154,7 +154,7 @@ private: wxString output = logfileName + wxT(".log"); //ensure uniqueness - for (int i = 1; zen::somethingExists(wxToZ(output)); ++i) + for (int i = 1; zen::somethingExists(toZ(output)); ++i) output = logfileName + wxChar('_') + zen::toString<wxString>(i) + wxT(".log"); return output; @@ -171,8 +171,8 @@ private: //############################################################################################################################## BatchStatusHandler::BatchStatusHandler(bool runSilent, const wxString& jobName, - const wxString* logfileDirectory, - size_t logFileMaxCount, + const wxString& logfileDirectory, + size_t logFileCountMax, const xmlAccess::OnError handleError, const SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode int& returnVal) : @@ -184,12 +184,12 @@ BatchStatusHandler::BatchStatusHandler(bool runSilent, returnValue(returnVal), syncStatusFrame(*this, NULL, SyncStatus::SCANNING, runSilent, jobName) { - if (logfileDirectory && logFileMaxCount > 0) + if (logFileCountMax > 0) { try { - logFile.reset(new LogFile(*logfileDirectory, jobName)); - logFile->limitLogfileCount(logFileMaxCount); + logFile = std::make_shared<LogFile>(logfileDirectory, jobName); //throw FileError + logFile->limitLogfileCount(logFileCountMax); //throw FileError } catch (zen::FileError& error) { @@ -198,8 +198,6 @@ BatchStatusHandler::BatchStatusHandler(bool runSilent, throw BatchAbortProcess(); } } - - assert(runSilent || handleError != xmlAccess::ON_ERROR_EXIT); //shouldn't be selectable from GUI settings } @@ -255,16 +253,6 @@ BatchStatusHandler::~BatchStatusHandler() } -inline -void BatchStatusHandler::reportInfo(const Zstring& text) -{ - if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) //write file transfer information to log - errorLog.logMsg(zToWx(text), TYPE_INFO); //avoid spamming with file copy info: visually identifying warning messages has priority! however when saving to a log file wee need this info - - syncStatusFrame.setStatusText_NoUpdate(text); -} - - void BatchStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, StatusHandler::Process processID) { currentProcess = processID; @@ -290,13 +278,12 @@ void BatchStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, } -inline void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: - syncStatusFrame.incScannedObjects_NoUpdate(objectsProcessed); + syncStatusFrame.incScannedObjects_NoUpdate(objectsProcessed); //throw () break; case StatusHandler::PROCESS_COMPARING_CONTENT: case StatusHandler::PROCESS_SYNCHRONIZING: @@ -306,6 +293,18 @@ void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 da assert(false); break; } + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void BatchStatusHandler::reportInfo(const wxString& text) +{ + if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) //write file transfer information to log + errorLog.logMsg(text, TYPE_INFO); //avoid spamming with file copy info: visually identifying warning messages has priority! however when saving to a log file wee need this info + + syncStatusFrame.setStatusText_NoUpdate(text); + requestUiRefresh(); //throw AbortThisProcess } @@ -320,7 +319,8 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war { case xmlAccess::ON_ERROR_POPUP: { - //show popup and ask user how to handle warning + forceUiRefresh(); + bool dontWarnAgain = false; switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_SWITCH | ReturnWarningDlg::BUTTON_ABORT, warningMessage + wxT("\n\n") + _("Press \"Switch\" to open FreeFileSync GUI mode."), @@ -353,14 +353,15 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war } -ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorMessage) { switch (handleError_) { case xmlAccess::ON_ERROR_POPUP: { - bool ignoreNextErrors = false; + forceUiRefresh(); + bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, errorMessage, ignoreNextErrors)) @@ -369,10 +370,10 @@ ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMess if (ignoreNextErrors) //falsify only handleError_ = xmlAccess::ON_ERROR_IGNORE; errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: errorLog.logMsg(errorMessage, TYPE_ERROR); @@ -387,11 +388,11 @@ ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMess case xmlAccess::ON_ERROR_IGNORE: errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } assert(false); - return ErrorHandler::IGNORE_ERROR; //dummy value + return ProcessCallback::IGNORE_ERROR; //dummy value } @@ -405,7 +406,6 @@ void BatchStatusHandler::reportFatalError(const wxString& errorMessage) } -inline void BatchStatusHandler::forceUiRefresh() { syncStatusFrame.updateStatusDialogNow(); diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h index a7c16488..1803019e 100644 --- a/ui/batch_status_handler.h +++ b/ui/batch_status_handler.h @@ -25,8 +25,8 @@ class BatchStatusHandler : public StatusHandler public: BatchStatusHandler(bool runSilent, //defines: -start minimized and -quit immediately when finished const wxString& jobName, - const wxString* logfileDirectory, //non-empty if logging shall be active - size_t logFileMaxCount, + const wxString& logfileDirectory, + size_t logFileCountMax, //0 if logging shall be inactive const xmlAccess::OnError handleError, const zen::SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode int& returnVal); @@ -34,11 +34,11 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); - virtual ErrorHandler::Response reportError(const wxString& errorMessage); + virtual Response reportError(const wxString& errorMessage); virtual void reportFatalError(const wxString& errorMessage); private: diff --git a/ui/folder_pair.h b/ui/folder_pair.h index 770aceb3..893acdc7 100644 --- a/ui/folder_pair.h +++ b/ui/folder_pair.h @@ -17,6 +17,7 @@ #include "../shared/util.h" #include "../shared/string_conv.h" #include "../library/norm_filter.h" +#include "../shared/custom_button.h" namespace zen { @@ -50,25 +51,25 @@ public: { if (altSyncConfig.get()) { - basicPanel_.m_bpButtonAltSyncCfg->SetBitmapLabel(GlobalResources::instance().getImage(wxT("syncConfigSmall"))); - basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(wxString(_("Select alternate synchronization settings")) + wxT(" ") + common::LINE_BREAK + + setBitmapLabel(*basicPanel_.m_bpButtonAltSyncCfg, GlobalResources::instance().getImage(wxT("syncConfigSmall"))); + basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(wxString(_("Select alternate synchronization settings")) + wxT(" \n") + wxT("(") + getVariantName(altSyncConfig->syncConfiguration.var) + wxT(")")); } else { - basicPanel_.m_bpButtonAltSyncCfg->SetBitmapLabel(GlobalResources::instance().getImage(wxT("syncConfigSmallGrey"))); + setBitmapLabel(*basicPanel_.m_bpButtonAltSyncCfg, GlobalResources::instance().getImage(wxT("syncConfigSmallGrey"))); basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(_("Select alternate synchronization settings")); } //test for Null-filter if (isNullFilter(localFilter)) { - basicPanel_.m_bpButtonLocalFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterSmallGrey"))); + setBitmapLabel(*basicPanel_.m_bpButtonLocalFilter, GlobalResources::instance().getImage(wxT("filterSmallGrey"))); basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("No filter selected")); } else { - basicPanel_.m_bpButtonLocalFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterSmall"))); + setBitmapLabel(*basicPanel_.m_bpButtonLocalFilter, GlobalResources::instance().getImage(wxT("filterSmall"))); basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Filter is active")); } } @@ -103,26 +104,28 @@ protected: private: void OnLocalFilterCfgRemove(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfgRemoveConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfgRemoveConfirm), NULL, this); if (isNullFilter(localFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway basicPanel_.PopupMenu(contextMenu.get()); //show context menu } void OnAltSyncCfgRemove(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Remove alternate settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); + + wxMenuItem* itemRemove = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Remove alternate settings")); + contextMenu->Append(itemRemove); + contextMenu->Connect(itemRemove->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); if (!altSyncConfig.get()) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemRemove->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway basicPanel_.PopupMenu(contextMenu.get()); //show context menu } diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp index c268957e..d3c0bb8e 100644 --- a/ui/gui_generated.cpp +++ b/ui/gui_generated.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Mar 22 2011) +// C++ code generated with wxFormBuilder (version Jun 30 2011) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -439,7 +439,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const bSizerConfig->Add( bSizer151, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE|wxLB_SORT ); + m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB|wxLB_SORT ); m_listBoxHistory->SetToolTip( _("Last used configurations (press DEL to remove from list)") ); m_listBoxHistory->SetMinSize( wxSize( -1,40 ) ); @@ -990,7 +990,7 @@ BatchFolderPairGenerated::~BatchFolderPairGenerated() BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 460,420 ), wxDefaultSize ); + this->SetSizeHints( wxSize( 560,320 ), wxDefaultSize ); wxBoxSizer* bSizer54; bSizer54 = new wxBoxSizer( wxVERTICAL ); @@ -1021,18 +1021,13 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer87->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer87->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); + bSizer87->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); wxBoxSizer* bSizer70; bSizer70 = new wxBoxSizer( wxHORIZONTAL ); m_staticText44 = new wxStaticText( this, wxID_ANY, _("Create a batch file for automated synchronization. To start in batch mode simply double-click the file or execute via command line: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText44->Wrap( 500 ); + m_staticText44->Wrap( 460 ); bSizer70->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); m_bpButtonHelp = new wxBitmapButton( this, wxID_HELP, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); @@ -1040,19 +1035,9 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer70->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer69->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); - - m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP, 5 ); - - m_staticText531 = new wxStaticText( this, wxID_ANY, _("Configuration overview:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText531->Wrap( -1 ); - m_staticText531->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); + bSizer87->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer69->Add( m_staticText531, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); m_notebookSettings = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_panelOverview = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); @@ -1241,26 +1226,10 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer120->Add( 0, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - wxFlexGridSizer* fgSizer15; - fgSizer15 = new wxFlexGridSizer( 1, 2, 10, 10 ); - fgSizer15->SetFlexibleDirection( wxBOTH ); - fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticBoxSizer* sbSizer24; - sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Status feedback") ), wxVERTICAL ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_checkBoxSilent = new wxCheckBox( m_panelOverview, wxID_ANY, _("Silent mode"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxSilent->SetToolTip( _("Start minimized and write status information to a logfile") ); - - sbSizer24->Add( m_checkBoxSilent, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 14 ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer67->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 10 ); - fgSizer15->Add( sbSizer24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + wxBoxSizer* bSizer171; + bSizer171 = new wxBoxSizer( wxVERTICAL ); wxStaticBoxSizer* sbSizer25; sbSizer25 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); @@ -1270,60 +1239,83 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_choiceHandleError->SetSelection( 0 ); sbSizer25->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer15->Add( sbSizer25, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer171->Add( sbSizer25, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer120->Add( fgSizer15, 0, 0, 5 ); - - bSizer67->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 10 ); + bSizer67->Add( bSizer171, 0, wxTOP|wxBOTTOM|wxRIGHT, 10 ); m_panelOverview->SetSizer( bSizer67 ); m_panelOverview->Layout(); bSizer67->Fit( m_panelOverview ); m_notebookSettings->AddPage( m_panelOverview, _("Overview"), true ); - m_panelLogging = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelBatchSettings = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer117; bSizer117 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer119; - bSizer119 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer172; + bSizer172 = new wxBoxSizer( wxVERTICAL ); - m_staticText120 = new wxStaticText( m_panelLogging, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText120->Wrap( -1 ); - bSizer119->Add( m_staticText120, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticBoxSizer* sbSizer24; + sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelBatchSettings, wxID_ANY, _("Status feedback") ), wxVERTICAL ); - sbSizerLogfileDir = new wxStaticBoxSizer( new wxStaticBox( m_panelLogging, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + m_checkBoxSilent = new wxCheckBox( m_panelBatchSettings, wxID_ANY, _("Run minimized"), wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer24->Add( m_checkBoxSilent, 0, wxALL|wxEXPAND, 5 ); - m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizerLogfileDir->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( sbSizer24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_dirPickerLogfileDir = new FfsDirPickerCtrl( m_panelLogging, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); - sbSizerLogfileDir->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( 0, 5, 0, 0, 5 ); - bSizer119->Add( sbSizerLogfileDir, 1, wxEXPAND, 5 ); + sbSizerLogfileDir = new wxStaticBoxSizer( new wxStaticBox( m_panelBatchSettings, wxID_ANY, _("Logging") ), wxVERTICAL ); wxBoxSizer* bSizer152; bSizer152 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText96 = new wxStaticText( m_panelLogging, wxID_ANY, _("Maximum number of logfiles:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText96 = new wxStaticText( m_panelBatchSettings, wxID_ANY, _("Maximum number of logfiles:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText96->Wrap( -1 ); - bSizer152->Add( m_staticText96, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer152->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); bSizer152->Add( 0, 0, 1, wxEXPAND, 5 ); - m_spinCtrlLogCountMax = new wxSpinCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer152->Add( m_spinCtrlLogCountMax, 0, wxALL, 5 ); + m_spinCtrlLogCountMax = new wxSpinCtrl( m_panelBatchSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer152->Add( m_spinCtrlLogCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerLogfileDir->Add( bSizer152, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_panelLogfile = new wxPanel( m_panelBatchSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1721; + bSizer1721 = new wxBoxSizer( wxVERTICAL ); + + m_staticText94 = new wxStaticText( m_panelLogfile, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText94->Wrap( -1 ); + bSizer1721->Add( m_staticText94, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + wxBoxSizer* bSizer170; + bSizer170 = new wxBoxSizer( wxHORIZONTAL ); + + m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer170->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLogfileDir = new FfsDirPickerCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); + + bSizer170->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer1721->Add( bSizer170, 0, wxEXPAND, 5 ); - bSizer119->Add( bSizer152, 0, wxEXPAND, 5 ); + m_panelLogfile->SetSizer( bSizer1721 ); + m_panelLogfile->Layout(); + bSizer1721->Fit( m_panelLogfile ); + sbSizerLogfileDir->Add( m_panelLogfile, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer117->Add( bSizer119, 0, wxEXPAND|wxALL, 10 ); + bSizer172->Add( sbSizerLogfileDir, 0, wxEXPAND, 5 ); - m_panelLogging->SetSizer( bSizer117 ); - m_panelLogging->Layout(); - bSizer117->Fit( m_panelLogging ); - m_notebookSettings->AddPage( m_panelLogging, _("Logging"), false ); + bSizer117->Add( bSizer172, 1, wxEXPAND|wxALL, 10 ); + + m_panelBatchSettings->SetSizer( bSizer117 ); + m_panelBatchSettings->Layout(); + bSizer117->Fit( m_panelBatchSettings ); + m_notebookSettings->AddPage( m_panelBatchSettings, _("Batch settings"), false ); bSizer69->Add( m_notebookSettings, 1, wxEXPAND, 5 ); @@ -1364,7 +1356,6 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSyncSettings ), NULL, this ); m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); m_bpButtonRemovePair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRemoveTopFolderPair ), NULL, this ); - m_checkBoxSilent->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_spinCtrlLogCountMax->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BatchDlgGenerated::OnChangeMaxLogCountTxt ), NULL, this ); m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); @@ -1382,7 +1373,6 @@ BatchDlgGenerated::~BatchDlgGenerated() m_bpButtonSyncConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSyncSettings ), NULL, this ); m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); m_bpButtonRemovePair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRemoveTopFolderPair ), NULL, this ); - m_checkBoxSilent->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_spinCtrlLogCountMax->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BatchDlgGenerated::OnChangeMaxLogCountTxt ), NULL, this ); m_buttonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); @@ -1851,12 +1841,16 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); m_radioBtnAutomatic->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); m_buttonAutomatic->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncAutomaticDouble ), NULL, this ); m_radioBtnMirror->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); + m_buttonOneWay->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncMirrorDouble ), NULL, this ); m_radioBtnUpdate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncUpdateDouble ), NULL, this ); m_radioBtnCustom->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); m_buttonUpdate1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); + m_buttonUpdate1->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncCustomDouble ), NULL, this ); m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); @@ -1875,12 +1869,16 @@ SyncCfgDlgGenerated::~SyncCfgDlgGenerated() this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); m_radioBtnAutomatic->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); m_buttonAutomatic->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncAutomaticDouble ), NULL, this ); m_radioBtnMirror->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); + m_buttonOneWay->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncMirrorDouble ), NULL, this ); m_radioBtnUpdate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); m_buttonUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncUpdateDouble ), NULL, this ); m_radioBtnCustom->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); m_buttonUpdate1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); + m_buttonUpdate1->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncCustomDouble ), NULL, this ); m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); @@ -1996,8 +1994,10 @@ CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const w this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); m_buttonTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnTimeSizeDouble ), NULL, this ); m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); m_buttonContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnContentDouble ), NULL, this ); m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); m_choiceHandleSymlinks->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_button10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnOkay ), NULL, this ); @@ -2010,8 +2010,10 @@ CmpCfgDlgGenerated::~CmpCfgDlgGenerated() this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); m_buttonTimeSize->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnTimeSizeDouble ), NULL, this ); m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); m_buttonContent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnContentDouble ), NULL, this ); m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); m_choiceHandleSymlinks->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_button10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnOkay ), NULL, this ); @@ -2540,25 +2542,25 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer171->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink7 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink7->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink13 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Boost"), wxT("http://www.boost.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink13->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer171->Add( m_hyperlink13, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink14 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxFormBuilder"), wxT("http://wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink14->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + m_hyperlink7 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink7->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink11 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("MS Visual C++"), wxT("http://msdn.microsoft.com/library/60k1461a.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink11->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + + bSizer171->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); m_hyperlink16 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink16->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); bSizer167->Add( bSizer171, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM, 5 ); @@ -2575,26 +2577,21 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer172->Add( m_hyperlink15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink11 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("MS Visual C++"), wxT("http://msdn.microsoft.com/library/60k1461a.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink11->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer172->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink12 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Google Test"), wxT("http://code.google.com/p/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink12->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink17 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("inotify"), wxT("http://inotify.aiken.cz"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink17->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer172->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink18 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Unicode NSIS"), wxT("http://www.scratchpaper.com"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink18->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_hyperlink14 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxFormBuilder"), wxT("http://wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink14->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + + bSizer172->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer167->Add( bSizer172, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); bSizerCodeInfo->Add( bSizer167, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); @@ -3026,7 +3023,7 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w bSizer24->Add( bSizer99, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); - m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY ); m_textCtrlMessage->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer24->Add( m_textCtrlMessage, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); diff --git a/ui/gui_generated.h b/ui/gui_generated.h index 13a4ea00..1659503c 100644 --- a/ui/gui_generated.h +++ b/ui/gui_generated.h @@ -1,15 +1,16 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Mar 22 2011) +// C++ code generated with wxFormBuilder (version Jun 30 2011) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// -#ifndef __gui_generated__ -#define __gui_generated__ +#ifndef __GUI_GENERATED_H__ +#define __GUI_GENERATED_H__ +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> #include <wx/intl.h> - class CustomComboBox; class CustomGridLeft; class CustomGridMiddle; @@ -85,26 +86,17 @@ protected: wxBoxSizer* bSizerPanelHolder; wxPanel* m_panelTopButtons; wxBoxSizer* bSizerTopButtons; - wxStaticText* m_staticTextCmpVariant; - wxButtonWithImage* m_buttonCompare; wxButton* m_buttonAbort; wxBitmapButton* m_bpButtonCmpConfig; - - wxStaticText* m_staticTextSyncVariant; wxBitmapButton* m_bpButtonSyncConfig; wxButtonWithImage* m_buttonStartSync; - wxPanel* m_panelDirectoryPairs; wxStaticBoxSizer* sbSizerDirLeft; wxPanel* m_panelTopMiddle; - wxBitmapButton* m_bpButtonSwapSides; - - - wxStaticBoxSizer* sbSizerDirRight; wxBitmapButton* m_bpButtonAddPair; wxScrolledWindow* m_scrolledWindowFolderPairs; @@ -117,17 +109,14 @@ protected: CustomGridRight* m_gridRight; wxPanel* m_panelConfig; wxBoxSizer* bSizerConfig; - wxBitmapButton* m_bpButtonSave; wxBitmapButton* m_bpButtonLoad; wxListBox* m_listBoxHistory; wxPanel* m_panelFilter; - wxBitmapButton* m_bpButtonFilter; wxCheckBox* m_checkBoxHideFilt; wxPanel* m_panelStatistics; wxBoxSizer* bSizerStatistics; - wxStaticBitmap* m_bitmapCreate; wxTextCtrl* m_textCtrlCreate; wxStaticBitmap* m_bitmapUpdate; @@ -136,10 +125,8 @@ protected: wxTextCtrl* m_textCtrlDelete; wxStaticBitmap* m_bitmapData; wxTextCtrl* m_textCtrlData; - wxPanel* m_panelViewFilter; wxBoxSizer* bSizerViewFilter; - ToggleButton* m_bpButtonSyncCreateLeft; ToggleButton* m_bpButtonSyncDirOverwLeft; ToggleButton* m_bpButtonSyncDeleteLeft; @@ -154,19 +141,12 @@ protected: ToggleButton* m_bpButtonSyncDirOverwRight; ToggleButton* m_bpButtonSyncCreateRight; ToggleButton* m_bpButtonConflict; - wxPanel* m_panelStatusBar; - wxStaticText* m_staticTextStatusLeft; - wxStaticLine* m_staticline9; - wxStaticText* m_staticTextStatusMiddle; - wxStaticLine* m_staticline10; - wxStaticText* m_staticTextStatusRight; - wxStaticBitmap* m_bitmap15; // Virtual event handlers, overide them in your derived class @@ -248,9 +228,6 @@ private: protected: - - - public: wxPanel* m_panelLeft; wxTextCtrl* m_directoryLeft; @@ -282,7 +259,6 @@ protected: wxPanel* m_panelLeft; wxPanel* m_panelRight; - public: wxBitmapButton* m_bpButtonRemovePair; wxTextCtrl* m_directoryLeft; @@ -309,43 +285,30 @@ protected: wxStaticBitmap* m_bitmap27; wxPanel* m_panel8; wxStaticText* m_staticText56; - - wxStaticText* m_staticText44; wxBitmapButton* m_bpButtonHelp; - - wxStaticLine* m_staticline10; - wxStaticText* m_staticText531; wxNotebook* m_notebookSettings; wxPanel* m_panelOverview; wxBitmapButton* m_bpButtonCmpConfig; - wxStaticText* m_staticTextCmpVariant; - wxBitmapButton* m_bpButtonFilter; - wxStaticText* m_staticTextSyncVariant; - wxBitmapButton* m_bpButtonSyncConfig; - wxBoxSizer* sbSizerMainPair; wxPanel* m_panelMainPair; wxStaticText* m_staticText532; wxStaticText* m_staticText5411; wxBoxSizer* bSizerAddFolderPairs; - - - wxCheckBox* m_checkBoxSilent; - wxChoice* m_choiceHandleError; - wxPanel* m_panelLogging; - wxStaticText* m_staticText120; + wxPanel* m_panelBatchSettings; + wxCheckBox* m_checkBoxSilent; wxStaticBoxSizer* sbSizerLogfileDir; - wxTextCtrl* m_textCtrlLogfileDir; - FfsDirPickerCtrl* m_dirPickerLogfileDir; wxStaticText* m_staticText96; - wxSpinCtrl* m_spinCtrlLogCountMax; + wxPanel* m_panelLogfile; + wxStaticText* m_staticText94; + wxTextCtrl* m_textCtrlLogfileDir; + FfsDirPickerCtrl* m_dirPickerLogfileDir; wxButton* m_buttonSave; wxButton* m_buttonLoad; wxButton* m_button6; @@ -358,7 +321,6 @@ protected: virtual void OnSyncSettings( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddFolderPair( wxCommandEvent& event ) { event.Skip(); } virtual void OnRemoveTopFolderPair( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCheckSilent( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeMaxLogCountTxt( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveBatchJob( wxCommandEvent& event ) { event.Skip(); } @@ -392,7 +354,6 @@ class CompareStatusGenerated : public wxPanel private: protected: - wxBoxSizer* bSizer42; wxBoxSizer* bSizerFilesFound; wxStaticText* m_staticText321; @@ -403,22 +364,18 @@ protected: wxStaticText* m_staticText117; wxStaticText* m_staticTextDataRemaining; wxStaticText* m_staticText118; - wxBoxSizer* sSizerSpeed; wxStaticText* m_staticText104; wxStaticText* m_staticTextSpeed; - wxBoxSizer* sSizerTimeRemaining; wxStaticText* m_staticTextTimeRemFixed; wxStaticText* m_staticTextTimeRemaining; - wxBoxSizer* sSizerTimeElapsed; wxStaticText* m_staticTextTimeElapsed; wxStaticText* m_staticText30; wxTextCtrl* m_textCtrlStatus; wxGauge* m_gauge2; - public: CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL ); @@ -447,7 +404,6 @@ protected: wxRadioButton* m_radioBtnCustom; wxButton* m_buttonUpdate1; wxStaticText* m_staticText9; - wxBoxSizer* bSizer201; wxStaticBoxSizer* sbSizerErrorHandling; wxChoice* m_choiceHandleError; @@ -458,9 +414,6 @@ protected: FfsDirPickerCtrl* m_dirPickerCustomDelFolder; wxButton* m_buttonOK; wxButton* m_button16; - - - wxStaticBitmap* m_bitmapDatabase; wxBoxSizer* sbSizerSyncDirections; wxStaticText* m_staticText21; @@ -468,36 +421,33 @@ protected: wxStaticLine* m_staticline3; wxBoxSizer* bSizerLeftOnly; wxStaticBitmap* m_bitmapLeftOnly; - wxBitmapButton* m_bpButtonLeftOnly; wxBoxSizer* bSizerRightOnly; wxStaticBitmap* m_bitmapRightOnly; - wxBitmapButton* m_bpButtonRightOnly; wxBoxSizer* bSizerLeftNewer; wxStaticBitmap* m_bitmapLeftNewer; - wxBitmapButton* m_bpButtonLeftNewer; wxBoxSizer* bSizerRightNewer; wxStaticBitmap* m_bitmapRightNewer; - wxBitmapButton* m_bpButtonRightNewer; wxBoxSizer* bSizerDifferent; wxStaticBitmap* m_bitmapDifferent; - wxBitmapButton* m_bpButtonDifferent; wxBoxSizer* bSizerConflict; wxStaticBitmap* m_bitmapConflict; - wxBitmapButton* m_bpButtonConflict; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnSyncAutomatic( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncAutomaticDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncMirror( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncMirrorDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncUpdate( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncUpdateDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncCustom( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncCustomDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeDeletionHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnApply( wxCommandEvent& event ) { event.Skip(); } @@ -533,7 +483,6 @@ protected: wxButton* m_buttonContent; wxStaticLine* m_staticline14; wxBitmapButton* m_bpButtonHelp; - wxChoice* m_choiceHandleSymlinks; wxButton* m_button10; wxButton* m_button6; @@ -541,7 +490,9 @@ protected: // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnTimeSize( wxCommandEvent& event ) { event.Skip(); } + virtual void OnTimeSizeDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnContent( wxCommandEvent& event ) { event.Skip(); } + virtual void OnContentDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnShowHelp( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } @@ -563,12 +514,9 @@ class SyncStatusDlgGenerated : public wxFrame private: protected: - - wxStaticBitmap* m_bitmapStatus; wxStaticText* m_staticTextStatus; wxAnimationCtrl* m_animationControl1; - wxBoxSizer* bSizer31; wxBoxSizer* bSizerObjectsRemaining; wxStaticText* m_staticText25; @@ -582,7 +530,6 @@ protected: wxStaticText* m_staticText98; wxStaticText* m_staticTextDataProcessed; wxStaticText* m_staticText99; - wxStaticText* m_staticText55; wxStaticText* m_staticTextTimeElapsed; wxBoxSizer* bSizerProgressText; @@ -591,18 +538,13 @@ protected: wxBoxSizer* bSizerSpeed; wxStaticText* m_staticText108; wxStaticText* m_staticTextSpeed; - - wxButton* m_buttonOK; wxButton* m_buttonPause; wxButton* m_buttonAbort; - wxBoxSizer* bSizerRemTime; - wxStaticText* m_staticText21; wxStaticText* m_staticTextTimeRemaining; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIconize( wxIconizeEvent& event ) { event.Skip(); } @@ -654,13 +596,9 @@ class HelpDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap25; wxPanel* m_panel8; - wxStaticText* m_staticText56; - - wxNotebook* m_notebook1; wxScrolledWindow* m_scrolledWindow1; wxStaticText* m_staticText59; @@ -705,50 +643,42 @@ class AboutDlgGenerated : public wxDialog private: protected: - wxPanel* m_panel5; wxStaticBitmap* m_bitmap11; wxStaticText* m_build; - wxPanel* m_panel33; wxBoxSizer* bSizerCodeInfo; wxStaticText* m_staticText72; wxHyperlinkCtrl* m_hyperlink9; wxHyperlinkCtrl* m_hyperlink10; - wxHyperlinkCtrl* m_hyperlink7; wxHyperlinkCtrl* m_hyperlink13; - wxHyperlinkCtrl* m_hyperlink14; + wxHyperlinkCtrl* m_hyperlink7; + wxHyperlinkCtrl* m_hyperlink11; wxHyperlinkCtrl* m_hyperlink16; wxHyperlinkCtrl* m_hyperlink8; wxHyperlinkCtrl* m_hyperlink15; - wxHyperlinkCtrl* m_hyperlink11; wxHyperlinkCtrl* m_hyperlink12; - wxHyperlinkCtrl* m_hyperlink17; wxHyperlinkCtrl* m_hyperlink18; + wxHyperlinkCtrl* m_hyperlink14; wxHyperlinkCtrl* m_hyperlink21; wxScrolledWindow* m_scrolledWindowTranslators; wxBoxSizer* bSizerTranslators; wxStaticText* m_staticText54; - wxFlexGridSizer* fgSizerTranslators; wxStaticLine* m_staticline3; wxStaticText* m_staticText131; wxStaticLine* m_staticline12; wxStaticBitmap* m_bitmap9; wxHyperlinkCtrl* m_hyperlink1; - wxHyperlinkCtrl* m_hyperlink3; wxAnimationCtrl* m_animationControl1; wxStaticBitmap* m_bitmap10; wxHyperlinkCtrl* m_hyperlink2; - wxHyperlinkCtrl* m_hyperlink6; wxStaticBitmap* m_bitmapTransl; wxStaticLine* m_staticline2; - wxStaticBitmap* m_bitmap13; wxHyperlinkCtrl* m_hyperlink5; - wxButton* m_buttonOkay; // Virtual event handlers, overide them in your derived class @@ -771,16 +701,13 @@ class ErrorDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap10; wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxIgnoreErrors; - wxButton* m_buttonIgnore; wxButton* m_buttonRetry; wxButton* m_buttonAbort; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIgnore( wxCommandEvent& event ) { event.Skip(); } @@ -803,15 +730,12 @@ class WarningDlgGenerated : public wxDialog private: protected: - wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxDontShowAgain; - wxButton* m_buttonIgnore; wxButton* m_buttonSwitch; wxButton* m_buttonAbort; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIgnore( wxCommandEvent& event ) { event.Skip(); } @@ -835,16 +759,13 @@ class QuestionDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap10; wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxDontAskAgain; - wxButton* m_buttonYes; wxButton* m_buttonNo; wxButton* m_buttonCancel; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnYes( wxCommandEvent& event ) { event.Skip(); } @@ -867,13 +788,9 @@ class DeleteDlgGenerated : public wxDialog private: protected: - - wxStaticBitmap* m_bitmap12; wxStaticText* m_staticTextHeader; - wxCheckBox* m_checkBoxDeleteBothSides; - wxCheckBox* m_checkBoxUseRecycler; wxTextCtrl* m_textCtrlMessage; wxButton* m_buttonOK; @@ -905,10 +822,8 @@ protected: wxStaticBitmap* m_bitmap26; wxPanel* m_panel8; wxStaticText* m_staticTexHeader; - wxStaticText* m_staticText44; wxBitmapButton* m_bpButtonHelp; - wxPanel* m_panel13; wxStaticLine* m_staticline10; wxStaticText* m_staticText45; @@ -917,12 +832,10 @@ protected: wxStaticText* m_staticText85; wxStaticText* m_staticText181; wxStaticText* m_staticText1811; - wxStaticBitmap* m_bitmapInclude; wxTextCtrl* m_textCtrlInclude; wxStaticBitmap* m_bitmapExclude; wxTextCtrl* m_textCtrlExclude; - wxStaticBitmap* m_bitmapFilterDate; wxStaticText* m_staticText103; wxSpinCtrl* m_spinCtrlTimespan; @@ -935,7 +848,6 @@ protected: wxSpinCtrl* m_spinCtrlMaxSize; wxChoice* m_choiceUnitMaxSize; wxButton* m_button9; - wxButton* m_button10; wxButton* m_button17; @@ -968,7 +880,6 @@ protected: wxBitmapButton* m_bpButton29; wxBitmapButton* m_bpButton30; wxButton* m_button9; - wxButton* m_button28; wxButton* m_button29; @@ -997,24 +908,17 @@ private: protected: wxStaticBitmap* m_bitmapSettings; - wxPanel* m_panel8; wxStaticText* m_staticText56; - wxCheckBox* m_checkBoxCopyLocked; wxCheckBox* m_checkBoxCopyPermissions; wxStaticLine* m_staticline10; wxStaticText* m_staticText100; - wxButtonWithImage* m_buttonResetDialogs; - - wxGrid* m_gridCustomCommand; wxBitmapButton* m_bpButtonAddRow; wxBitmapButton* m_bpButtonRemoveRow; - wxButton* m_button9; - wxButton* m_buttonOkay; wxButton* m_button29; @@ -1047,7 +951,6 @@ protected: wxStaticLine* m_staticline16; wxStaticText* m_staticTextVariant; wxStaticLine* m_staticline14; - wxStaticText* m_staticText94; wxStaticBitmap* m_bitmapCreate; wxTextCtrl* m_textCtrlCreateL; @@ -1059,14 +962,10 @@ protected: wxTextCtrl* m_textCtrlCreateR; wxTextCtrl* m_textCtrlUpdateR; wxTextCtrl* m_textCtrlDeleteR; - wxStaticBitmap* m_bitmapData; - wxTextCtrl* m_textCtrlData; - wxStaticLine* m_staticline12; wxCheckBox* m_checkBoxDontShowAgain; - wxButton* m_button16; // Virtual event handlers, overide them in your derived class @@ -1111,7 +1010,6 @@ private: protected: wxStaticText* m_staticText101; wxTextCtrl* m_textCtrlSearchTxt; - wxCheckBox* m_checkBoxMatchCase; wxButton* m_buttonFindNext; wxButton* m_button29; @@ -1130,4 +1028,4 @@ public: }; -#endif //__gui_generated__ +#endif //__GUI_GENERATED_H__ diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp index 3319d07a..43293829 100644 --- a/ui/gui_status_handler.cpp +++ b/ui/gui_status_handler.cpp @@ -7,7 +7,6 @@ #include "gui_status_handler.h" #include "small_dlgs.h" #include "msg_popup.h" -#include "../shared/system_constants.h" #include "main_dlg.h" #include <wx/wupdlock.h> #include "../shared/global_func.h" @@ -73,12 +72,6 @@ void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) } -void CompareStatusHandler::reportInfo(const Zstring& text) -{ - mainDlg.compareStatus->setStatusText_NoUpdate(text); -} - - void CompareStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID) { currentProcess = processID; @@ -103,31 +96,39 @@ void CompareStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal } -inline void CompareStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: - mainDlg.compareStatus->incScannedObjects_NoUpdate(objectsProcessed); + mainDlg.compareStatus->incScannedObjects_NoUpdate(objectsProcessed); //throw () break; case StatusHandler::PROCESS_COMPARING_CONTENT: - mainDlg.compareStatus->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); + mainDlg.compareStatus->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); //throw () break; case StatusHandler::PROCESS_SYNCHRONIZING: case StatusHandler::PROCESS_NONE: assert(false); break; } + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void CompareStatusHandler::reportInfo(const wxString& text) +{ + mainDlg.compareStatus->setStatusText_NoUpdate(text); + requestUiRefresh(); //throw AbortThisProcess } -ErrorHandler::Response CompareStatusHandler::reportError(const wxString& message) +ProcessCallback::Response CompareStatusHandler::reportError(const wxString& message) { if (ignoreErrors) - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, @@ -135,23 +136,23 @@ ErrorHandler::Response CompareStatusHandler::reportError(const wxString& message { case ReturnErrorDlg::BUTTON_IGNORE: ignoreErrors = ignoreNextErrors; - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: abortThisProcess(); } assert(false); - return ErrorHandler::IGNORE_ERROR; //dummy return value + return ProcessCallback::IGNORE_ERROR; //dummy return value } void CompareStatusHandler::reportFatalError(const wxString& errorMessage) { - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); //show message and abort: currently there are no fatal errors during comparison that can be ignored bool dummy = false; @@ -167,7 +168,7 @@ void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& w if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also return; - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); //show popup and ask user how to handle warning bool dontWarnAgain = false; @@ -188,7 +189,6 @@ void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& w } -inline void CompareStatusHandler::forceUiRefresh() { mainDlg.compareStatus->updateStatusPanelNow(); @@ -223,9 +223,9 @@ SyncStatusHandler::~SyncStatusHandler() //finalize error log if (abortIsRequested()) - errorLog.logMsg(wxString(_("Synchronization aborted!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_ERROR); + errorLog.logMsg(_("Synchronization aborted!") + " \n" + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_ERROR); else if (totalErrors > 0) - errorLog.logMsg(wxString(_("Synchronization completed with errors!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_WARNING); + errorLog.logMsg(_("Synchronization completed with errors!") + " \n" + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_WARNING); else errorLog.logMsg(_("Synchronization completed successfully!"), TYPE_INFO); @@ -239,16 +239,6 @@ SyncStatusHandler::~SyncStatusHandler() } -inline -void SyncStatusHandler::reportInfo(const Zstring& text) -{ - //if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) - errorLog.logMsg(zToWx(text), TYPE_INFO); - - syncStatusFrame.setStatusText_NoUpdate(text); -} - - void SyncStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID) { switch (processID) @@ -266,14 +256,26 @@ void SyncStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, P } -inline void SyncStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { - syncStatusFrame.incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); + syncStatusFrame.incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); //throw () + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void SyncStatusHandler::reportInfo(const wxString& text) +{ + //if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) + errorLog.logMsg(text, TYPE_INFO); + + syncStatusFrame.setStatusText_NoUpdate(text); //throw () + + requestUiRefresh(); //throw AbortThisProccess } -ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMessage) { switch (handleError_) { @@ -281,10 +283,10 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa break; case ON_GUIERROR_IGNORE: errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } - syncStatusFrame.updateStatusDialogNow(); + forceUiRefresh(); bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, @@ -294,10 +296,10 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa case ReturnErrorDlg::BUTTON_IGNORE: handleError_ = ignoreNextErrors ? ON_GUIERROR_IGNORE : ON_GUIERROR_POPUP; errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: errorLog.logMsg(errorMessage, TYPE_ERROR); @@ -306,7 +308,7 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa assert (false); errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } @@ -327,11 +329,11 @@ void SyncStatusHandler::reportWarning(const wxString& warningMessage, bool& warn case ON_GUIERROR_IGNORE: return; //if errors are ignored, then warnings should also } - if (!warningActive) return; + if (!warningActive) + return; - syncStatusFrame.updateStatusDialogNow(); + forceUiRefresh(); - //show popup and ask user how to handle warning bool dontWarnAgain = false; switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT, warningMessage, diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h index 7f41e649..45d429b1 100644 --- a/ui/gui_status_handler.h +++ b/ui/gui_status_handler.h @@ -29,10 +29,10 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); - virtual ErrorHandler::Response reportError(const wxString& text); + virtual Response reportError(const wxString& text); virtual void reportFatalError(const wxString& errorMessage); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); @@ -55,10 +55,10 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); - virtual ErrorHandler::Response reportError(const wxString& text); + virtual Response reportError(const wxString& text); virtual void reportFatalError(const wxString& errorMessage); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp index c5e8ef72..2256329a 100644 --- a/ui/main_dlg.cpp +++ b/ui/main_dlg.cpp @@ -17,7 +17,6 @@ #include <wx/display.h> #include <wx/app.h> #include <boost/bind.hpp> -#include "../shared/system_constants.h" #include "../library/custom_grid.h" #include "../shared/custom_button.h" #include "../shared/custom_combo_box.h" @@ -97,31 +96,8 @@ public: case xmlAccess::MERGE_GUI: case xmlAccess::MERGE_GUI_BATCH: - if (droppedFiles.size() == 1) - { - mainDlg_.loadConfiguration(droppedFiles[0]); - return false; - } - else - { - xmlAccess::XmlGuiConfig guiCfg; - try - { - convertConfig(droppedFiles, guiCfg); //throw (xmlAccess::FfsXmlError) - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return false; - } - } - mainDlg_.setCurrentConfiguration(guiCfg); - return false; - } + mainDlg_.loadConfiguration(droppedFiles); + return false; case xmlAccess::MERGE_OTHER: //=> return true: change directory selection via drag and drop @@ -177,7 +153,7 @@ private: virtual MainConfiguration getMainConfig() const { - return mainDlg.getCurrentConfiguration().mainCfg; + return mainDlg.getConfig().mainCfg; } virtual void OnAltSyncCfgChange() @@ -356,18 +332,30 @@ MainDialog::MainDialog(const wxString& cfgFileName, xmlAccess::XmlGlobalSettings { xmlAccess::XmlGuiConfig guiCfg; //structure to receive gui settings, already defaulted!! - wxString currentConfigFile = cfgFileName; //this one has priority - if (currentConfigFile.empty()) currentConfigFile = settings.gui.lastUsedConfigFile; //next: suggest name of last used selection - if (currentConfigFile.empty() || !fileExists(wxToZ(currentConfigFile))) currentConfigFile = lastRunConfigName(); //if above fails... + std::vector<wxString> filenames; + if (!cfgFileName.empty()) //1. this one has priority + filenames.push_back(cfgFileName); + else //next: use last used selection + { + filenames = settings.gui.lastUsedConfigFiles; //2. now try last used files + + //check if one of the files is not existing (this shall not be an error!) + if (std::find_if(filenames.begin(), filenames.end(), + [](const wxString& filename) { return !fileExists(toZ(filename)); }) != filenames.end()) + filenames.clear(); + + if (filenames.empty()) + { + if (fileExists(toZ(lastRunConfigName()))) //3. try to load auto-save config + filenames.push_back(lastRunConfigName()); + } + } bool loadCfgSuccess = false; - if (!cfgFileName.empty() || fileExists(wxToZ(currentConfigFile))) + if (!filenames.empty()) try { //load XML - std::vector<wxString> filenames; - filenames.push_back(currentConfigFile); - xmlAccess::convertConfig(filenames, guiCfg); //throw (xmlAccess::FfsXmlError) loadCfgSuccess = true; @@ -385,7 +373,7 @@ MainDialog::MainDialog(const wxString& cfgFileName, xmlAccess::XmlGlobalSettings settings, startComparisonImmediately); - setLastUsedConfig(currentConfigFile, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors + setLastUsedConfig(filenames, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors } @@ -397,6 +385,8 @@ MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg, init(guiCfg, settings, startComparison); + + setLastUsedConfig(std::vector<wxString>(), guiCfg); } @@ -479,6 +469,11 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, m_panelStatusBar ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), NULL, this); //---------------------------------------------------------------------------------- + //register context: quick variant selection + m_bpButtonCmpConfig ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSelectCompVariant), NULL, this); + m_bpButtonSyncConfig->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSelectSyncVariant), NULL, this); + + globalSettings = &settings; gridDataView.reset(new zen::GridView); contextMenu.reset(new wxMenu); //initialize right-click context menu; will be dynamically re-created on each R-mouse-click @@ -496,8 +491,6 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, syncPreview.reset(new SyncPreview(this)); - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - SetIcon(*GlobalResources::instance().programIcon); //set application icon //notify about (logical) application main window => program won't quit, but stay on this dialog @@ -510,7 +503,7 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, //initialize and load configuration readGlobalSettings(); - setCurrentConfiguration(guiCfg); + setConfig(guiCfg); //set icons for this dialog m_buttonCompare->setBitmapFront(GlobalResources::instance().getImage(wxT("compare"))); @@ -618,7 +611,7 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, //some convenience: if FFS is started with a *.ffs_gui file as commandline parameter AND all directories contained exist, comparison shall be started right off if (startComparison) { - const zen::MainConfiguration currMainCfg = getCurrentConfiguration().mainCfg; + const zen::MainConfiguration currMainCfg = getConfig().mainCfg; const bool allFoldersExist = !DirNotFound()(currMainCfg.firstPair) && std::find_if(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), DirNotFound()) == currMainCfg.additionalPairs.end(); @@ -629,8 +622,6 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, } } //---------------------------------------------------------------------------------------------------------------------------------------------------------------- - - addFileToCfgHistory(lastRunConfigName()); //make sure <Last session> is always part of history list } @@ -651,12 +642,12 @@ void MainDialog::cleanUp(bool saveLastUsedConfig) m_gridMiddle->release(); m_gridRight ->release(); - writeGlobalSettings(); //set before saving last used config since this will reset "currentConfigFileName" + writeGlobalSettings(); //set before saving last used config since "activeConfigFiles" will be replaced //save configuration if (saveLastUsedConfig) { - const xmlAccess::XmlGuiConfig guiCfg = getCurrentConfiguration(); + const xmlAccess::XmlGuiConfig guiCfg = getConfig(); try { xmlAccess::writeConfig(guiCfg, lastRunConfigName()); @@ -689,9 +680,10 @@ void MainDialog::readGlobalSettings() m_gridLeft->setColumnAttributes(globalSettings->gui.columnAttribLeft); m_gridRight->setColumnAttributes(globalSettings->gui.columnAttribRight); - //load list of last used configuration files (in reverse order) - std::for_each(globalSettings->gui.cfgFileHistory.rbegin(), globalSettings->gui.cfgFileHistory.rend(), - boost::bind(&MainDialog::addFileToCfgHistory, this, _1)); + //load list of last used configuration files + std::vector<wxString> cfgFileNames = globalSettings->gui.cfgFileHistory; + cfgFileNames.push_back(lastRunConfigName()); //make sure <Last session> is always part of history list + addFileToCfgHistory(cfgFileNames); //load list of last used folders std::for_each(globalSettings->gui.folderHistoryLeft.rbegin(), @@ -738,8 +730,8 @@ void MainDialog::writeGlobalSettings() if (m_listBoxHistory->GetClientObject(i)) cfgFileHistory.push_back(static_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(i))->name_); - globalSettings->gui.cfgFileHistory = cfgFileHistory; - globalSettings->gui.lastUsedConfigFile = currentConfigFileName; + globalSettings->gui.cfgFileHistory = cfgFileHistory; + globalSettings->gui.lastUsedConfigFiles = activeConfigFiles; //write list of last used folders globalSettings->gui.folderHistoryLeft.clear(); @@ -825,15 +817,18 @@ void MainDialog::OnIdleEvent(wxEvent& event) event.Skip(); } +namespace +{ +//fast replacement for wxString modelling exponential growth +typedef Zbase<wchar_t> zxString; //for use with UI texts +} + void MainDialog::copySelectionToClipboard(CustomGrid& selectedGrid) { const std::set<size_t> selectedRows = getSelectedRows(&selectedGrid); if (selectedRows.size() > 0) { - //fast replacement for wxString modelling exponential growth - typedef Zbase<wchar_t> zxString; - zxString clipboardString; //perf: wxString doesn't model exponential growth and so is out const int colCount = selectedGrid.GetNumberCols(); @@ -899,7 +894,7 @@ public: mainDlg->clearStatusBar(); //register abort button - mainDlg->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this ); + mainDlg->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion), NULL, this ); mainDlg->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), NULL, this); } @@ -907,7 +902,7 @@ public: { //de-register abort button mainDlg->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), NULL, this); - mainDlg->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this ); + mainDlg->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion ), NULL, this ); mainDlg->enableAllElements(); } @@ -959,7 +954,7 @@ public: } private: - void OnAbortCompare(wxCommandEvent& event) //handle abort button click + void OnAbortDeletion(wxCommandEvent& event) //handle abort button click { abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) } @@ -968,7 +963,10 @@ private: { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) + { abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) + return; + } event.Skip(); } @@ -1001,12 +999,6 @@ void MainDialog::deleteSelectedFiles(const std::set<size_t>& viewSelectionLeft, globalSettings->gui.deleteOnBothSides, globalSettings->gui.useRecyclerForManualDeletion) == ReturnSmallDlg::BUTTON_OKAY) { - if (globalSettings->gui.useRecyclerForManualDeletion && !zen::recycleBinExists()) - { - wxMessageBox(_("Recycle Bin not yet supported for this system!")); - return; - } - try { //handle errors when deleting files/folders @@ -1048,17 +1040,17 @@ void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir) GetNames(wxString& nameIn, wxString& dirIn) : name_(nameIn), dir_(dirIn) {} virtual void visit(const FileMapping& fileObj) { - name_ = zToWx(fileObj.getFullName<side>()); - dir_ = zToWx(fileObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + name_ = toWx(fileObj.getFullName<side>()); + dir_ = toWx(fileObj.getFullName<side>().BeforeLast(FILE_NAME_SEPARATOR)); } virtual void visit(const SymLinkMapping& linkObj) { - name_ = zToWx(linkObj.getFullName<side>()); - dir_ = zToWx(linkObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR)); + name_ = toWx(linkObj.getFullName<side>()); + dir_ = toWx(linkObj.getFullName<side>().BeforeLast(FILE_NAME_SEPARATOR)); } virtual void visit(const DirMapping& dirObj) { - dir_ = name_ = zToWx(dirObj.getFullName<side>()); + dir_ = name_ = toWx(dirObj.getFullName<side>()); } wxString& name_; @@ -1119,10 +1111,10 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const if (name.empty()) { if (leftSide) - zen::shellExecute(wxString(L"\"") + zToWx(fsObj->getBaseDirPf<LEFT_SIDE>()) + L"\""); + zen::shellExecute(wxString(L"\"") + fsObj->getBaseDirPf<LEFT_SIDE>() + "\""); //zen::shellExecute(wxString(wxT("explorer ")) + L"\"" + zToWx(fsObj->getBaseDirPf<LEFT_SIDE>()) + L"\""); else - zen::shellExecute(wxString(L"\"") + zToWx(fsObj->getBaseDirPf<RIGHT_SIDE>()) + L"\""); + zen::shellExecute(wxString(L"\"") + fsObj->getBaseDirPf<RIGHT_SIDE>() + "\""); //zen::shellExecute(wxString(wxT("explorer ")) + L"\"" + zToWx(fsObj->getBaseDirPf<RIGHT_SIDE>()) + L"\""); return; } @@ -1131,8 +1123,8 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const else { //fallback - dir = zToWx(zen::getFormattedDirectoryName(wxToZ(firstFolderPair->getLeftDir()))); - dirCo = zToWx(zen::getFormattedDirectoryName(wxToZ(firstFolderPair->getRightDir()))); + dir = toWx(zen::getFormattedDirectoryName(toZ(firstFolderPair->getLeftDir()))); + dirCo = toWx(zen::getFormattedDirectoryName(toZ(firstFolderPair->getRightDir()))); if (!leftSide) std::swap(dir, dirCo); @@ -1177,6 +1169,10 @@ void MainDialog::clearStatusBar() void MainDialog::disableAllElements(bool enableAbort) { + //when changing consider: comparison, synchronization, manual deletion + + EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window! + //disables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion m_panelViewFilter ->Disable(); m_bpButtonCmpConfig ->Disable(); @@ -1211,6 +1207,8 @@ void MainDialog::disableAllElements(bool enableAbort) void MainDialog::enableAllElements() { + EnableCloseButton(true); + m_panelViewFilter ->Enable(); m_bpButtonCmpConfig ->Enable(); m_panelFilter ->Enable(); @@ -1798,13 +1796,13 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_EXT if (exFilterCandidateObj.size() > 0 && !exFilterCandidateObj.begin()->second) //non empty && no directory { - const Zstring filename = exFilterCandidateObj.begin()->first.AfterLast(common::FILE_NAME_SEPARATOR); + const Zstring filename = exFilterCandidateObj.begin()->first.AfterLast(FILE_NAME_SEPARATOR); if (filename.find(Zchar('.')) != Zstring::npos) //be careful: AfterLast would return the whole string if '.' were not found! { const Zstring extension = filename.AfterLast(Zchar('.')); //add context menu item - wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + zToWx(extension)); + wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + "*." + extension); menuItemExclExt->SetBitmap(GlobalResources::instance().getImage(wxT("filterSmall"))); contextMenu->Append(menuItemExclExt); @@ -1821,9 +1819,9 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_OBJ wxMenuItem* menuItemExclObj = NULL; if (exFilterCandidateObj.size() == 1) - menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + zToWx(exFilterCandidateObj.begin()->first.AfterLast(common::FILE_NAME_SEPARATOR))); + menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + exFilterCandidateObj.begin()->first.AfterLast(FILE_NAME_SEPARATOR)); else if (exFilterCandidateObj.size() > 1) - menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>")); + menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + _("<multiple selection>")); if (menuItemExclObj != NULL) { @@ -1853,7 +1851,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) { //some trick to translate default external apps on the fly: 1. "open in explorer" 2. "start directly" //wxString description = wxGetTranslation(i->first); - wxString description = zen::translate(i->first); + wxString description = zen::translate(i->first.c_str()); if (description.empty()) description = wxT(" "); //wxWidgets doesn't like empty items @@ -1909,8 +1907,10 @@ void MainDialog::OnContextExcludeExtension(wxCommandEvent& event) updateFilterButtons(); //do not fully apply filter, just exclude new items - addExcludeFiltering(gridDataView->getDataTentative(), newExclude); - //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + std::for_each(gridDataView->getDataTentative().begin(), gridDataView->getDataTentative().end(), + [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); }); + + //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); if (currentCfg.hideFilteredElements) @@ -1936,9 +1936,9 @@ void MainDialog::OnContextExcludeObject(wxCommandEvent& event) if (i != objCont->selectedObjects.begin()) newExclude += Zstr("\n"); - newExclude += common::FILE_NAME_SEPARATOR + i->first; + newExclude += FILE_NAME_SEPARATOR + i->first; if (i->second) //is directory - newExclude += common::FILE_NAME_SEPARATOR; + newExclude += FILE_NAME_SEPARATOR; } //add to filter config @@ -1950,8 +1950,10 @@ void MainDialog::OnContextExcludeObject(wxCommandEvent& event) updateFilterButtons(); //do not fully apply filter, just exclude new items - addExcludeFiltering(gridDataView->getDataTentative(), newExclude); - //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + std::for_each(gridDataView->getDataTentative().begin(), gridDataView->getDataTentative().end(), + [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); }); + + //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); if (currentCfg.hideFilteredElements) @@ -2009,18 +2011,18 @@ void MainDialog::OnContextSyncDirRight(wxCommandEvent& event) void MainDialog::OnContextRimLabelLeft(wxGridEvent& event) { - int ctxtElementId = 1000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++ctxtElementId, _("Customize...")); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnLeft), NULL, this); + + wxMenuItem* menuItemCustomize = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Customize...")); + contextMenu->Append(menuItemCustomize); + contextMenu->Connect(menuItemCustomize->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnLeft), NULL, this); contextMenu->AppendSeparator(); - wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), ++ctxtElementId, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); + wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); contextMenu->Append(itemAutoAdjust); itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsLeft); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustLeft), NULL, this); + contextMenu->Connect(itemAutoAdjust->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustLeft), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2028,19 +2030,18 @@ void MainDialog::OnContextRimLabelLeft(wxGridEvent& event) void MainDialog::OnContextRimLabelRight(wxGridEvent& event) { - int ctxtElementId = 1000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++ctxtElementId, _("Customize...")); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnRight), NULL, this); + wxMenuItem* menuItemCustomize = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Customize...")); + contextMenu->Append(menuItemCustomize); + contextMenu->Connect(menuItemCustomize->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnRight), NULL, this); contextMenu->AppendSeparator(); - wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), ++ctxtElementId, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); + wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); contextMenu->Append(itemAutoAdjust); itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsRight); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustRight), NULL, this); + contextMenu->Connect(itemAutoAdjust->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustRight), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2092,20 +2093,19 @@ void MainDialog::OnContextAutoAdjustRight(wxCommandEvent& event) void MainDialog::OnContextMiddle(wxGridEvent& event) { - int contextItemID = 2000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++contextItemID, _("Include all rows")); + wxMenuItem* menuItemInclude = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Include all rows")); + contextMenu->Append(menuItemInclude); if (gridDataView->rowsTotal() == 0) - contextMenu->Enable(contextItemID, false); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextIncludeAll), NULL, this); - + menuItemInclude->Enable(false); + contextMenu->Connect(menuItemInclude->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextIncludeAll), NULL, this); - contextMenu->Append(++contextItemID, _("Exclude all rows")); + wxMenuItem* menuItemExclude = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Exclude all rows")); + contextMenu->Append(menuItemExclude); if (gridDataView->rowsTotal() == 0) - contextMenu->Enable(contextItemID, false); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextExcludeAll), NULL, this); + menuItemExclude->Enable(false); + contextMenu->Connect(menuItemExclude->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextExcludeAll), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2113,15 +2113,13 @@ void MainDialog::OnContextMiddle(wxGridEvent& event) void MainDialog::OnContextMiddleLabel(wxGridEvent& event) { - int contextItemID = 2000; - contextMenu.reset(new wxMenu); //re-create context menu - wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), ++contextItemID, _("Synchronization Preview")); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncView), NULL, this); + wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Synchronization Preview")); + contextMenu->Connect(itemSyncPreview->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncView), NULL, this); - wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), ++contextItemID, _("Comparison Result")); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextComparisonView), NULL, this); + wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Comparison Result")); + contextMenu->Connect(itemCmpResult->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextComparisonView), NULL, this); if (syncPreview->previewIsEnabled()) itemSyncPreview->SetBitmap(GlobalResources::instance().getImage(wxT("syncViewSmall"))); @@ -2215,6 +2213,138 @@ void MainDialog::OnContextSyncView(wxCommandEvent& event) } +struct CtxtSelectionCmpVar : public wxObject +{ + CtxtSelectionCmpVar(CompareVariant var) : compareVar(var) {} + CompareVariant compareVar; +}; + + +void MainDialog::OnContextSelectCompVariant(wxMouseEvent& event) +{ + contextMenu.reset(new wxMenu); //re-create context menu + + wxMenuItem* itemSizeDate = new wxMenuItem(contextMenu.get(), wxID_ANY, _("File size and date"), L"", wxITEM_RADIO); + contextMenu->Append(itemSizeDate); + contextMenu->Connect(itemSizeDate->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetCompVariant), + new CtxtSelectionCmpVar(CMP_BY_TIME_SIZE), //ownership passed! + this); + + wxMenuItem* itemContent = new wxMenuItem(contextMenu.get(), wxID_ANY, _("File content"), L"", wxITEM_RADIO); + contextMenu->Append(itemContent); + contextMenu->Connect(itemContent->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetCompVariant), + new CtxtSelectionCmpVar(CMP_BY_CONTENT), //ownership passed! + this); + + //--------------------------------------------------------------- + xmlAccess::XmlGuiConfig cfg = getConfig(); + + switch (cfg.mainCfg.compareVar) + { + case CMP_BY_TIME_SIZE: + itemSizeDate->Check(); + break; + case CMP_BY_CONTENT: + itemContent->Check(); + break; + } + + PopupMenu(contextMenu.get()); //show context menu +} + + +struct CtxtSelectionSyncVar : public wxObject +{ + CtxtSelectionSyncVar(SyncConfig::Variant var) : syncVar(var) {} + SyncConfig::Variant syncVar; +}; + + +void MainDialog::OnContextSelectSyncVariant(wxMouseEvent& event) +{ + contextMenu.reset(new wxMenu); //re-create context menu + + wxMenuItem* itemAuto = new wxMenuItem(contextMenu.get(), wxID_ANY, _("<Automatic>"), L"", wxITEM_RADIO); + contextMenu->Append(itemAuto); + contextMenu->Connect(itemAuto->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::AUTOMATIC), //ownership passed! + this); + + wxMenuItem* itemMirror = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Mirror ->>"), L"", wxITEM_RADIO); + contextMenu->Append(itemMirror); + contextMenu->Connect(itemMirror->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::MIRROR), //ownership passed! + this); + + wxMenuItem* itemUpdate = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Update ->"), L"", wxITEM_RADIO); + contextMenu->Append(itemUpdate); + contextMenu->Connect(itemUpdate->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::UPDATE), //ownership passed! + this); + + wxMenuItem* itemCustom = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Custom"), L"", wxITEM_RADIO); + contextMenu->Append(itemCustom); + contextMenu->Connect(itemCustom->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::CUSTOM), //ownership passed! + this); + + //--------------------------------------------------------------- + xmlAccess::XmlGuiConfig cfg = getConfig(); + + switch (cfg.mainCfg.syncConfiguration.var) + { + case SyncConfig::AUTOMATIC: + itemAuto->Check(); + break; + case SyncConfig::MIRROR: + itemMirror->Check(); + break; + case SyncConfig::UPDATE: + itemUpdate->Check(); + break; + case SyncConfig::CUSTOM: + itemCustom->Check(); + break; + } + + PopupMenu(contextMenu.get()); //show context menu +} + + +void MainDialog::OnSetCompVariant(wxCommandEvent& event) +{ + CtxtSelectionCmpVar* selection = dynamic_cast<CtxtSelectionCmpVar*>(event.m_callbackUserData); + if (selection) + { + currentCfg.mainCfg.compareVar = selection->compareVar; + applyCompareConfig(); + } +} + + +void MainDialog::OnSetSyncVariant(wxCommandEvent& event) +{ + CtxtSelectionSyncVar* selection = dynamic_cast<CtxtSelectionSyncVar*>(event.m_callbackUserData); + if (selection) + { + currentCfg.mainCfg.syncConfiguration.var = selection->syncVar; + applySyncConfig(); + } +} + + void MainDialog::OnDirSelected(wxFileDirPickerEvent& event) { //left and right directory text-control and dirpicker are synchronized by MainFolderDragDrop automatically @@ -2232,58 +2362,69 @@ void MainDialog::OnDirSelected(wxFileDirPickerEvent& event) wxString getFormattedHistoryElement(const wxString& filename) { - Zstring output = wxToZ(filename).AfterLast(common::FILE_NAME_SEPARATOR); - if (output.EndsWith(Zstr(".ffs_gui"))) - output = output.BeforeLast(Zstr('.')); - return zToWx(output); + wxString output = afterLast(filename, FILE_NAME_SEPARATOR); + if (endsWith(output, ".ffs_gui")) + output = beforeLast(output, '.'); + return output; } -void MainDialog::addFileToCfgHistory(const wxString& cfgFile) +void MainDialog::addFileToCfgHistory(const std::vector<wxString>& filenames) { - wxString filename = cfgFile; - if (filename.empty()) - filename = lastRunConfigName(); + std::deque<bool> selections(m_listBoxHistory->GetCount()); - //only (still) existing files should be included in the list - if (util::fileExists(wxToZ(filename), 200) == util::EXISTING_FALSE) //potentially slow network access: wait 200ms - return; + std::for_each(filenames.begin(), filenames.end(), + [&](wxString filename) + { + //only (still) existing files should be included in the list + if (util::fileExists(toZ(filename), 200) == util::EXISTING_FALSE) //potentially slow network access: wait 200ms + return; - int posFound = -1; + int posFound = -1; - for (int i = 0; i < static_cast<int>(m_listBoxHistory->GetCount()); ++i) - if (m_listBoxHistory->GetClientObject(i)) + for (int i = 0; i < static_cast<int>(m_listBoxHistory->GetCount()); ++i) { - const wxString& filenameTmp = static_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(i))->name_; - - //tests if the same filenames are specified, even if they are relative to the current working directory/include symlinks or \\?\ prefix - if (util::sameFileSpecified(wxToZ(filename), wxToZ(filenameTmp))) + wxClientDataString* cData = dynamic_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(i)); + if (cData) { - posFound = i; - break; + const wxString& filenameTmp = cData->name_; + + //tests if the same filenames are specified, even if they are relative to the current working directory/include symlinks or \\?\ prefix + if (util::sameFileSpecified(toZ(filename), toZ(filenameTmp))) + { + posFound = i; + break; + } } } - if (posFound != -1) - { - //if entry is in the list, then jump to element - m_listBoxHistory->SetSelection(posFound); - } - else - { - int newPos = -1; - //the default config file should receive another name on GUI - if (util::sameFileSpecified(wxToZ(lastRunConfigName()), wxToZ(filename))) - newPos = m_listBoxHistory->Append(_("<Last session>"), new wxClientDataString(filename)); //insert at beginning of list + if (posFound != -1) + selections[posFound] = true; else - newPos = m_listBoxHistory->Append(getFormattedHistoryElement(filename), new wxClientDataString(filename)); //insert at beginning of list + { + int newPos = -1; + //the default config file should receive a different name on GUI + if (util::sameFileSpecified(toZ(lastRunConfigName()), toZ(filename))) + newPos = m_listBoxHistory->Append(_("<Last session>"), new wxClientDataString(filename)); + else + newPos = m_listBoxHistory->Append(getFormattedHistoryElement(filename), new wxClientDataString(filename)); - m_listBoxHistory->SetSelection(newPos); - } + selections.insert(selections.begin() + newPos, true); + } + }); + + assert(selections.size() == m_listBoxHistory->GetCount()); - //keep maximal size of history list - //if (m_comboHistory->GetCount() > globalSettings->gui.cfgHistoryMax) - // m_comboHistory->Delete(globalSettings->gui.cfgHistoryMax); + //do not apply selections immediately but only when needed! + //this prevents problems with m_listBoxHistory losing keyboard selection focus if identical selection is redundantly reapplied + for (int pos = 0; pos < static_cast<int>(selections.size()); ++pos) + if (m_listBoxHistory->IsSelected(pos) != selections[pos]) + { + if (selections[pos]) + m_listBoxHistory->SetSelection(pos); + else + m_listBoxHistory->Deselect(pos); + } } @@ -2307,33 +2448,35 @@ void MainDialog::OnSaveConfig(wxCommandEvent& event) bool MainDialog::trySaveConfig() //return true if saved successfully { - wxString defaultFileName = currentConfigFileName.empty() ? wxT("SyncSettings.ffs_gui") : currentConfigFileName; - //attention: currentConfigFileName may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config! + wxString defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxT("SyncSettings.ffs_gui"); + //attention: activeConfigFiles may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config! if (defaultFileName.EndsWith(wxT(".ffs_batch"))) defaultFileName.Replace(wxT(".ffs_batch"), wxT(".ffs_gui"), false); - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, - wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { - const wxString newFileName = filePicker.GetPath(); + const wxString filename = filePicker.GetPath(); + const xmlAccess::XmlGuiConfig guiCfg = getConfig(); - if (zen::fileExists(wxToZ(newFileName))) + //write config to XML + try { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - return trySaveConfig(); //retry - } + xmlAccess::writeConfig(guiCfg, filename); + setLastUsedConfig(filename, guiCfg); - if (writeConfigurationToXml(newFileName)) - { pushStatusInformation(_("Configuration saved!")); return true; } + catch (const xmlAccess::FfsXmlError& error) + { + wxMessageBox(error.msg().c_str(), _("Error"), wxOK | wxICON_ERROR); + } } return false; @@ -2344,12 +2487,19 @@ void MainDialog::OnLoadConfig(wxCommandEvent& event) { wxFileDialog filePicker(this, wxEmptyString, - beforeLast(currentConfigFileName, common::FILE_NAME_SEPARATOR), //set default dir: empty string if "currentConfigFileName" is empty or has no path separator + beforeLast(activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxString(), FILE_NAME_SEPARATOR), //set default dir: empty string if "activeConfigFiles" is empty or has no path separator wxEmptyString, - wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch"), wxFD_OPEN); + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch"), + wxFD_OPEN | wxFD_MULTIPLE); if (filePicker.ShowModal() == wxID_OK) - loadConfiguration(filePicker.GetPath()); + { + wxArrayString tmp; + filePicker.GetPaths(tmp); + std::vector<wxString> fileNames(tmp.begin(), tmp.end()); + + loadConfiguration(fileNames); + } } @@ -2358,21 +2508,33 @@ void MainDialog::OnNewConfig(wxCommandEvent& event) if (!saveOldConfig()) //notify user about changed settings return; - setCurrentConfiguration(xmlAccess::XmlGuiConfig()); + xmlAccess::XmlGuiConfig emptyCfg; + setConfig(emptyCfg); - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - currentConfigFileName.clear(); + setLastUsedConfig(std::vector<wxString>(), emptyCfg); } void MainDialog::OnLoadFromHistory(wxCommandEvent& event) { - if (event.GetClientObject()) + wxArrayInt selections; + m_listBoxHistory->GetSelections(selections); + + std::vector<wxString> filenames; + std::for_each(selections.begin(), selections.end(), + [&](int pos) { - const wxString filename = static_cast<wxClientDataString*>(event.GetClientObject())->name_; - loadConfiguration(filename); + wxClientDataString* cData = dynamic_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(pos)); + if (cData) + filenames.push_back(cData->name_); + }); - addFileToCfgHistory(currentConfigFileName); //in case user cancelled saving old config: restore selection to currently active config file + if (!filenames.empty()) + { + loadConfiguration(filenames); + + //in case user cancelled saving old config, selection is wrong: so reapply it! + addFileToCfgHistory(activeConfigFiles); } } @@ -2380,9 +2542,11 @@ void MainDialog::OnLoadFromHistory(wxCommandEvent& event) bool MainDialog::saveOldConfig() //return false on user abort { //notify user about changed settings - if (globalSettings->optDialogs.popupOnConfigChange && !currentConfigFileName.empty()) //only if check is active and non-default config file loaded + if (globalSettings->optDialogs.popupOnConfigChange && + //only if check is active and non-default config file loaded + (activeConfigFiles.size() != 1 || activeConfigFiles[0] != lastRunConfigName())) { - if (lastConfigurationSaved != getCurrentConfiguration()) + if (lastConfigurationSaved != getConfig()) { bool dontShowAgain = !globalSettings->optDialogs.popupOnConfigChange; @@ -2408,14 +2572,46 @@ bool MainDialog::saveOldConfig() //return false on user abort void MainDialog::loadConfiguration(const wxString& filename) { - if (!filename.IsEmpty()) + std::vector<wxString> filenames; + filenames.push_back(filename); + + loadConfiguration(filenames); +} + + +void MainDialog::loadConfiguration(const std::vector<wxString>& filenames) +{ + if (filenames.empty()) + return; + + if (!saveOldConfig()) + return; + + //load XML + xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!! + try { - if (!saveOldConfig()) - return; + //allow reading batch configurations also + xmlAccess::convertConfig(filenames, newGuiCfg); //throw (xmlAccess::FfsXmlError) - if (readConfigurationFromXml(filename)) - pushStatusInformation(_("Configuration loaded!")); + setLastUsedConfig(filenames, newGuiCfg); + pushStatusInformation(_("Configuration loaded!")); } + catch (const xmlAccess::FfsXmlError& error) + { + if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) + { + setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors + wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); + } + else + { + wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); + return; + } + } + + setConfig(newGuiCfg); } @@ -2424,21 +2620,27 @@ void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) const int keyCode = event.GetKeyCode(); if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE) { - //try to delete the currently selected config history item - //const int selectedItem = m_listBoxHistory->GetCurrentSelection(); - const int selectedItem = m_listBoxHistory->GetSelection(); - if (selectedItem != wxNOT_FOUND) + //delete currently selected config history items + wxArrayInt tmp; + m_listBoxHistory->GetSelections(tmp); + + std::set<int> selections(tmp.begin(), tmp.end()); //sort ascending! + + int shift = 0; + std::for_each(selections.begin(), selections.end(), + [&](int pos) { - m_listBoxHistory->Delete(selectedItem); + m_listBoxHistory->Delete(pos + shift); + --shift; + }); - //set selection on next element - if (m_listBoxHistory->GetCount() > 0) - { - int newSelection = selectedItem; - if (newSelection >= static_cast<int>(m_listBoxHistory->GetCount())) - newSelection = m_listBoxHistory->GetCount() - 1; - m_listBoxHistory->SetSelection(newSelection); - } + //set active selection on next element to allow "batch-deletion" by holding down DEL key + if (!selections.empty() && m_listBoxHistory->GetCount() > 0) + { + int newSelection = *selections.begin(); + if (newSelection >= static_cast<int>(m_listBoxHistory->GetCount())) + newSelection = m_listBoxHistory->GetCount() - 1; + m_listBoxHistory->SetSelection(newSelection); } return; //"swallow" event @@ -2450,6 +2652,7 @@ void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) void MainDialog::OnClose(wxCloseEvent& event) { + /* if (m_buttonAbort->IsShown()) //delegate to "abort" button if available { wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); //simulate button click @@ -2461,18 +2664,21 @@ void MainDialog::OnClose(wxCloseEvent& event) return; } } - else //regular destruction handling + */ + + //regular destruction handling + if (event.CanVeto()) { - if (event.CanVeto()) + const bool cancelled = !saveOldConfig(); //notify user about changed settings + if (cancelled) { - const bool cancelled = !saveOldConfig(); //notify user about changed settings - if (cancelled) - { - event.Veto(); - return; - } + //attention: this Veto() does NOT cancel system shutdown: application will block + //in saveOldConfig() within a modal dialog, so system will just kill the app + event.Veto(); + return; } } + Destroy(); } @@ -2516,80 +2722,30 @@ void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event) } -bool MainDialog::readConfigurationFromXml(const wxString& filename) +void MainDialog::setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig) { - //load XML - xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!! - bool parsingError = true; - try - { - //allow reading batch configurations also - std::vector<wxString> filenames; - filenames.push_back(filename); - - xmlAccess::convertConfig(filenames, newGuiCfg); //throw (xmlAccess::FfsXmlError) - - parsingError = false; - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return false; - } - } - - setCurrentConfiguration(newGuiCfg); - - setLastUsedConfig(filename, parsingError ? xmlAccess::XmlGuiConfig() : newGuiCfg); //simulate changed config on parsing errors - - return !parsingError; + std::vector<wxString> filenames; + filenames.push_back(filename); + setLastUsedConfig(filenames, guiConfig); } -void MainDialog::setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig) +void MainDialog::setLastUsedConfig(const std::vector<wxString>& filenames, const xmlAccess::XmlGuiConfig& guiConfig) { - addFileToCfgHistory(filename); //put filename on list of last used config files - - //set title - if (filename.empty() || filename == lastRunConfigName()) - { - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - currentConfigFileName.clear(); - } - else - { - SetTitle(filename); - currentConfigFileName = filename; - } - + activeConfigFiles = filenames; lastConfigurationSaved = guiConfig; -} + addFileToCfgHistory(activeConfigFiles); //put filename on list of last used config files -bool MainDialog::writeConfigurationToXml(const wxString& filename) -{ - const xmlAccess::XmlGuiConfig guiCfg = getCurrentConfiguration(); - - //write config to XML - try - { - xmlAccess::writeConfig(guiCfg, filename); - setLastUsedConfig(filename, guiCfg); - return true; - } - catch (const xmlAccess::FfsXmlError& error) - { - wxMessageBox(error.msg().c_str(), _("Error"), wxOK | wxICON_ERROR); - return false; - } + //set title + if (activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName()) + SetTitle(activeConfigFiles[0]); + else + SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); } -void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCfg) +void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg) { currentCfg = newGuiCfg; @@ -2608,13 +2764,13 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf updateFilterButtons(); //set first folder pair - firstFolderPair->setValues(zToWx(currentCfg.mainCfg.firstPair.leftDirectory), - zToWx(currentCfg.mainCfg.firstPair.rightDirectory), + firstFolderPair->setValues(toWx(currentCfg.mainCfg.firstPair.leftDirectory), + toWx(currentCfg.mainCfg.firstPair.rightDirectory), currentCfg.mainCfg.firstPair.altSyncConfig, currentCfg.mainCfg.firstPair.localFilter); - addLeftFolderToHistory( zToWx(currentCfg.mainCfg.firstPair.leftDirectory)); //another hack: wxCombobox::Insert() asynchronously sends message - addRightFolderToHistory(zToWx(currentCfg.mainCfg.firstPair.rightDirectory)); //overwriting a later wxCombobox::SetValue()!!! :( + addLeftFolderToHistory( toWx(currentCfg.mainCfg.firstPair.leftDirectory)); //another hack: wxCombobox::Insert() asynchronously sends message + addRightFolderToHistory(toWx(currentCfg.mainCfg.firstPair.rightDirectory)); //overwriting a later wxCombobox::SetValue()!!! :( //clear existing additional folder pairs clearAddFolderPairs(); @@ -2641,22 +2797,22 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf inline FolderPairEnh getEnhancedPair(const DirectoryPair* panel) { - return FolderPairEnh(wxToZ(panel->getLeftDir()), - wxToZ(panel->getRightDir()), + return FolderPairEnh(toZ(panel->getLeftDir()), + toZ(panel->getRightDir()), panel->getAltSyncConfig(), panel->getAltFilterConfig()); } -xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const +xmlAccess::XmlGuiConfig MainDialog::getConfig() const { xmlAccess::XmlGuiConfig guiCfg = currentCfg; //load settings whose ownership lies not in currentCfg: //first folder pair - guiCfg.mainCfg.firstPair = FolderPairEnh(wxToZ(firstFolderPair->getLeftDir()), - wxToZ(firstFolderPair->getRightDir()), + guiCfg.mainCfg.firstPair = FolderPairEnh(toZ(firstFolderPair->getLeftDir()), + toZ(firstFolderPair->getRightDir()), firstFolderPair->getAltSyncConfig(), firstFolderPair->getAltFilterConfig()); @@ -2679,15 +2835,15 @@ const wxString& MainDialog::lastRunConfigName() } -void MainDialog::refreshGridAfterFilterChange(const int delay) +void MainDialog::refreshGridAfterFilterChange(int delay) { //signal UI that grids need to be refreshed on next Update() m_gridLeft ->ForceRefresh(); m_gridMiddle->ForceRefresh(); m_gridRight ->ForceRefresh(); - m_gridLeft ->Update(); // - m_gridMiddle->Update(); //show changes resulting from ForceRefresh() - m_gridRight ->Update(); // + //m_gridLeft ->Update(); // + //m_gridMiddle->Update(); //show changes resulting from ForceRefresh() + //m_gridRight ->Update(); // if (currentCfg.hideFilteredElements) { @@ -2732,13 +2888,14 @@ void MainDialog::OnConfigureFilter(wxCommandEvent& event) void MainDialog::OnGlobalFilterOpenContext(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnGlobalFilterRemConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnGlobalFilterRemConfirm), NULL, this); if (isNullFilter(currentCfg.mainCfg.globalFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway PopupMenu(contextMenu.get()); //show context menu } @@ -2950,12 +3107,12 @@ void MainDialog::updateFilterButtons() //global filter: test for Null-filter if (isNullFilter(currentCfg.mainCfg.globalFilter)) { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOff"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOff"))); m_bpButtonFilter->SetToolTip(_("No filter selected")); } else { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOn"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOn"))); m_bpButtonFilter->SetToolTip(_("Filter is active")); } @@ -2987,7 +3144,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) //class handling status display and error messages CompareStatusHandler statusHandler(*this); - const std::vector<zen::FolderPairCfg> cmpConfig = zen::extractCompareCfg(getCurrentConfiguration().mainCfg); + const std::vector<zen::FolderPairCfg> cmpConfig = zen::extractCompareCfg(getConfig().mainCfg); //GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization LockHolder dummy2; @@ -2998,8 +3155,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) } //begin comparison - zen::CompareProcess comparison(currentCfg.mainCfg.handleSymlinks, - globalSettings->fileTimeTolerance, + zen::CompareProcess comparison(globalSettings->fileTimeTolerance, globalSettings->optDialogs, statusHandler); @@ -3013,7 +3169,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) //play (optional) sound notification after sync has completed (GUI and batch mode) const wxString soundFile = zen::getResourceDir() + wxT("Compare_Complete.wav"); - if (fileExists(wxToZ(soundFile))) + if (fileExists(toZ(soundFile))) wxSound::Play(soundFile, wxSOUND_ASYNC); } catch (GuiAbortProcess&) @@ -3120,45 +3276,53 @@ void MainDialog::OnSyncSettings(wxCommandEvent& event) } -void MainDialog::OnCmpSettings(wxCommandEvent& event) +void MainDialog::applyCompareConfig() { - //show window right next to the compare-config button - wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); - windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; + //update compare variant name + m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")")); + m_panelTopButtons->Layout(); //adapt layout for variant text - const CompareVariant compareVarOld = currentCfg.mainCfg.compareVar; - const SymLinkHandling handleSymlinksOld = currentCfg.mainCfg.handleSymlinks; + //disable the sync button + syncPreview->enableSynchronization(false); - if (zen::showCompareCfgDialog(windowPos, - currentCfg.mainCfg.compareVar, - currentCfg.mainCfg.handleSymlinks) == ReturnSmallDlg::BUTTON_OKAY && - //check if settings were changed at all - (compareVarOld != currentCfg.mainCfg.compareVar || - handleSymlinksOld != currentCfg.mainCfg.handleSymlinks)) + //clear grids + gridDataView->clearAllRows(); + updateGuiGrid(); + + //convenience: change sync view + switch (currentCfg.mainCfg.compareVar) { - //update compare variant name - m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")")); - m_panelTopButtons->Layout(); //adapt layout for variant text + case CMP_BY_TIME_SIZE: + syncPreview->enablePreview(true); + break; + case CMP_BY_CONTENT: + syncPreview->enablePreview(false); + break; + } - //disable the sync button - syncPreview->enableSynchronization(false); + m_buttonCompare->SetFocus(); +} - //clear grids - gridDataView->clearAllRows(); - updateGuiGrid(); - //convenience: change sync view - switch (currentCfg.mainCfg.compareVar) - { - case CMP_BY_TIME_SIZE: - syncPreview->enablePreview(true); - break; - case CMP_BY_CONTENT: - syncPreview->enablePreview(false); - break; - } +void MainDialog::OnCmpSettings(wxCommandEvent& event) +{ + //show window right next to the compare-config button + //wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); + //windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; - m_buttonCompare->SetFocus(); + CompareVariant compareVarNew = currentCfg.mainCfg.compareVar; + SymLinkHandling handleSymlinkNew = currentCfg.mainCfg.handleSymlinks; + + if (zen::showCompareCfgDialog(compareVarNew, + handleSymlinkNew) == ReturnSmallDlg::BUTTON_OKAY && + //check if settings were changed at all + (compareVarNew != currentCfg.mainCfg.compareVar || + handleSymlinkNew != currentCfg.mainCfg.handleSymlinks)) + { + currentCfg.mainCfg.compareVar = compareVarNew; + currentCfg.mainCfg.handleSymlinks = handleSymlinkNew; + + applyCompareConfig(); } } @@ -3183,7 +3347,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) bool dontShowAgain = false; if (zen::showSyncPreviewDlg( - getCurrentConfiguration().mainCfg.getSyncVariantName(), + getConfig().mainCfg.getSyncVariantName(), zen::SyncStatistics(gridDataView->getDataTentative()), dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY) return; @@ -3198,8 +3362,10 @@ void MainDialog::OnStartSync(wxCommandEvent& event) { //PERF_START; + wxString activeFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxString(); + //class handling status updates and error messages - SyncStatusHandler statusHandler(this, currentCfg.handleError, zen::extractJobName(currentConfigFileName)); + SyncStatusHandler statusHandler(this, currentCfg.handleError, zen::extractJobName(activeFileName)); FolderComparison& dataToSync = gridDataView->getDataTentative(); @@ -3219,7 +3385,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) globalSettings->copyFilePermissions, statusHandler); - const std::vector<zen::FolderPairSyncCfg> syncProcessCfg = zen::extractSyncCfg(getCurrentConfiguration().mainCfg); + const std::vector<zen::FolderPairSyncCfg> syncProcessCfg = zen::extractSyncCfg(getConfig().mainCfg); //make sure syncProcessCfg and dataToSync have same size and correspond! if (syncProcessCfg.size() != dataToSync.size()) @@ -3229,7 +3395,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) //play (optional) sound notification after sync has completed (GUI and batch mode) const wxString soundFile = zen::getResourceDir() + wxT("Sync_Complete.wav"); - if (fileExists(wxToZ(soundFile))) + if (fileExists(toZ(soundFile))) wxSound::Play(soundFile, wxSOUND_ASYNC); } catch (GuiAbortProcess&) @@ -3452,7 +3618,7 @@ void MainDialog::OnSwapSides(wxCommandEvent& event) m_bpButtonSyncDirOverwRight->setActive(tmp); //swap grid information - zen::swapGrids(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + zen::swapGrids(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); } @@ -3651,14 +3817,14 @@ void MainDialog::OnAddFolderPair(wxCommandEvent& event) wxWindowUpdateLocker dummy(this); //avoid display distortion std::vector<FolderPairEnh> newPairs; - newPairs.push_back(getCurrentConfiguration().mainCfg.firstPair); + newPairs.push_back(getConfig().mainCfg.firstPair); addFolderPair(newPairs, true); //add pair in front of additonal pairs //clear first pair const FolderPairEnh cfgEmpty; - firstFolderPair->setValues(zToWx(cfgEmpty.leftDirectory), - zToWx(cfgEmpty.rightDirectory), + firstFolderPair->setValues(toWx(cfgEmpty.leftDirectory), + toWx(cfgEmpty.rightDirectory), cfgEmpty.altSyncConfig, cfgEmpty.localFilter); @@ -3673,7 +3839,7 @@ void MainDialog::OnAddFolderPair(wxCommandEvent& event) void MainDialog::updateFilterConfig() { - applyFiltering(gridDataView->getDataTentative(), getCurrentConfiguration().mainCfg); + applyFiltering(gridDataView->getDataTentative(), getConfig().mainCfg); refreshGridAfterFilterChange(400); } @@ -3681,7 +3847,7 @@ void MainDialog::updateFilterConfig() void MainDialog::applySyncConfig() { //update sync variant name - m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getCurrentConfiguration().mainCfg.getSyncVariantName() + wxT(")")); + m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getConfig().mainCfg.getSyncVariantName() + wxT(")")); m_panelTopButtons->Layout(); //adapt layout for variant text @@ -3708,7 +3874,7 @@ void MainDialog::applySyncConfig() wxWindow* parent_; } redetCallback(globalSettings->optDialogs.warningSyncDatabase, this); - zen::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative(), &redetCallback); + zen::redetermineSyncDirection(getConfig().mainCfg, gridDataView->getDataTentative(), &redetCallback); updateGuiGrid(); } @@ -3723,8 +3889,8 @@ void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event) const FolderPairEnh cfgSecond = getEnhancedPair(additionalFolderPairs[0]); //reset first pair - firstFolderPair->setValues(zToWx(cfgSecond.leftDirectory), - zToWx(cfgSecond.rightDirectory), + firstFolderPair->setValues(toWx(cfgSecond.leftDirectory), + toWx(cfgSecond.rightDirectory), cfgSecond.altSyncConfig, cfgSecond.localFilter); @@ -3780,43 +3946,55 @@ void MainDialog::updateGuiForFolderPair() m_bpButtonLocalFilter->Hide(); m_bpButtonAltSyncCfg->Hide(); - m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::instance().getImage(wxT("swap"))); + setBitmapLabel(*m_bpButtonSwapSides, GlobalResources::instance().getImage(wxT("swap"))); } else { m_bpButtonLocalFilter->Show(); m_bpButtonAltSyncCfg->Show(); - m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::instance().getImage(wxT("swapSlim"))); + setBitmapLabel(*m_bpButtonSwapSides, GlobalResources::instance().getImage(wxT("swapSlim"))); } m_panelTopMiddle->Layout(); - - int addPairHeight = 0; + int addPairMinimalHeight = 0; + int addPairOptimalHeight = 0; if (additionalFolderPairs.size() > 0) - addPairHeight = std::min<double>(1.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there - additionalFolderPairs[0]->GetSize().GetHeight(); + { + int pairHeight = additionalFolderPairs[0]->GetSize().GetHeight(); + addPairMinimalHeight = std::min<double>(1.5, additionalFolderPairs.size()) * pairHeight; //have 0.5 * height indicate that more folders are there + addPairOptimalHeight = std::min<double>(globalSettings->gui.maxFolderPairsVisible - 1 + 0.5, //subtract first/main folder pair and add 0.5 to indicate additional folders + additionalFolderPairs.size()) * pairHeight; + + addPairOptimalHeight = std::max(addPairOptimalHeight, addPairMinimalHeight); //implicitly handle corrupted values for "maxFolderPairsVisible" + } + + //######################################################################################################################## + //wxAUI hack: set minimum height to desired value, then call wxAuiPaneInfo::Fixed() to apply it + auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairOptimalHeight); + auiMgr.GetPane(m_panelDirectoryPairs).Fixed(); + auiMgr.Update(); + + //now make resizable again + auiMgr.GetPane(m_panelDirectoryPairs).Resizable(); + auiMgr.Update(); + //######################################################################################################################## //ensure additional folder pairs are at least partially visible - auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairHeight); + auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairMinimalHeight); auiMgr.Update(); m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size //m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window m_panelDirectoryPairs->Layout(); - - /* - #warning test - auiMgr.GetPane(m_panelDirectoryPairs).MaxSize(20, 20); - auiMgr.Update(); - */ } void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool addFront) { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // if (!newPairs.empty()) { @@ -3845,8 +4023,8 @@ void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this); //set alternate configuration - newPair->setValues(zToWx(i->leftDirectory), - zToWx(i->rightDirectory), + newPair->setValues(toWx(i->leftDirectory), + toWx(i->rightDirectory), i->altSyncConfig, i->localFilter); } @@ -3867,6 +4045,7 @@ void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool void MainDialog::removeAddFolderPair(size_t pos) { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // if (pos < additionalFolderPairs.size()) { @@ -3896,6 +4075,7 @@ void MainDialog::removeAddFolderPair(size_t pos) void MainDialog::clearAddFolderPairs() { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // additionalFolderPairs.clear(); bSizerAddFolderPairs->Clear(true); @@ -3917,8 +4097,6 @@ void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event) namespace { -typedef Zbase<wchar_t> zxString; - inline void addCellValue(zxString& exportString, const wxString& cellVal) { @@ -3934,20 +4112,16 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) { //get a filename const wxString defaultFileName = wxT("FileList.csv"); //proposal - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + wxEmptyString, + defaultFileName, + wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { const wxString newFileName = filePicker.GetPath(); - if (zen::fileExists(wxToZ(newFileName))) - { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - { - OnMenuExportFileList(event); //retry - return; - } - } zxString exportString; //perf: wxString doesn't model exponential growth and so is out @@ -4034,7 +4208,7 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) size_t bufferSize = 0; const wxCharBuffer utf8buffer = wxConvUTF8.cWC2MB(exportString.c_str(), exportString.size(), &bufferSize); - output.Write(common::BYTE_ORDER_MARK_UTF8, sizeof(common::BYTE_ORDER_MARK_UTF8) - 1); + output.Write(BYTE_ORDER_MARK_UTF8, sizeof(BYTE_ORDER_MARK_UTF8) - 1); output.Write(utf8buffer, bufferSize); pushStatusInformation(_("File list exported!")); } @@ -4049,7 +4223,7 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) void MainDialog::OnMenuBatchJob(wxCommandEvent& event) { //fill batch config structure - const xmlAccess::XmlGuiConfig currCfg = getCurrentConfiguration(); //get UP TO DATE config, with updated values for main and additional folders! + const xmlAccess::XmlGuiConfig currCfg = getConfig(); //get UP TO DATE config, with updated values for main and additional folders! const xmlAccess::XmlBatchConfig batchCfg = convertGuiToBatch(currCfg); @@ -4115,7 +4289,7 @@ void MainDialog::switchProgramLanguage(const int langID) //create new dialog with respect to new language zen::setLanguage(langID); //language is a global attribute - const xmlAccess::XmlGuiConfig currentGuiCfg = getCurrentConfiguration(); + const xmlAccess::XmlGuiConfig currentGuiCfg = getConfig(); cleanUp(false); //destructor's code: includes updating global settings @@ -4151,24 +4325,11 @@ bool MainDialog::SyncPreview::previewIsEnabled() const void MainDialog::SyncPreview::enablePreview(bool value) { - if (value) - { - syncPreviewEnabled = true; + syncPreviewEnabled = value; - //toggle display of sync preview in middle grid - mainDlg_->m_gridMiddle->enableSyncPreview(true); - - mainDlg_->Refresh(); - } - else - { - syncPreviewEnabled = false; - - //toggle display of sync preview in middle grid - mainDlg_->m_gridMiddle->enableSyncPreview(false); - - mainDlg_->Refresh(); - } + //toggle display of sync preview in middle grid + mainDlg_->m_gridMiddle->enableSyncPreview(value); + // mainDlg_->Refresh(); mainDlg_->updateGuiGrid(); } @@ -4176,15 +4337,15 @@ void MainDialog::SyncPreview::enablePreview(bool value) void MainDialog::SyncPreview::enableSynchronization(bool value) { + synchronizationEnabled = value; + if (value) { - synchronizationEnabled = true; mainDlg_->m_buttonStartSync->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT)); mainDlg_->m_buttonStartSync->setBitmapFront(GlobalResources::instance().getImage(wxT("sync"))); } else { - synchronizationEnabled = false; mainDlg_->m_buttonStartSync->SetForegroundColour(wxColor(128, 128, 128)); //Some colors seem to have problems with 16Bit color depth, well this one hasn't! mainDlg_->m_buttonStartSync->setBitmapFront(GlobalResources::instance().getImage(wxT("syncDisabled"))); } diff --git a/ui/main_dlg.h b/ui/main_dlg.h index 4d00ff2a..47adf4a9 100644 --- a/ui/main_dlg.h +++ b/ui/main_dlg.h @@ -46,8 +46,8 @@ public: ~MainDialog(); - void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion - void enableAllElements(); // + void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input + void enableAllElements(); //during long-running processes: comparison, deletion private: friend class CompareStatusHandler; @@ -68,18 +68,23 @@ private: void cleanUp(bool saveLastUsedConfig); //configuration load/save - bool readConfigurationFromXml(const wxString& filename); - bool writeConfigurationToXml(const wxString& filename); void setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig); + void setLastUsedConfig(const std::vector<wxString>& filenames, const xmlAccess::XmlGuiConfig& guiConfig); - xmlAccess::XmlGuiConfig getCurrentConfiguration() const; - void setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCfg); + xmlAccess::XmlGuiConfig getConfig() const; + void setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg); + + void loadConfiguration(const wxString& filename); + void loadConfiguration(const std::vector<wxString>& filenames); + + bool trySaveConfig(); //return true if saved successfully + bool saveOldConfig(); //return false on user abort static const wxString& lastRunConfigName(); xmlAccess::XmlGuiConfig lastConfigurationSaved; //support for: "Save changed configuration?" dialog //used when saving configuration - wxString currentConfigFileName; + std::vector<wxString> activeConfigFiles; //name of currently loaded config file (may be more than 1) void readGlobalSettings(); void writeGlobalSettings(); @@ -87,7 +92,8 @@ private: void initViewFilterButtons(); void updateFilterButtons(); - void addFileToCfgHistory(const wxString& filename); + void addFileToCfgHistory(const std::vector<wxString>& filenames); + void addLeftFolderToHistory(const wxString& leftFolder); void addRightFolderToHistory(const wxString& rightFolder); @@ -131,6 +137,14 @@ private: void OnContextSetLayout( wxMouseEvent& event); void OnGlobalKeyEvent( wxKeyEvent& event); + void OnContextSelectCompVariant( wxMouseEvent& event); + void OnContextSelectSyncVariant( wxMouseEvent& event); + + void applyCompareConfig(); + + void OnSetCompVariant(wxCommandEvent& event); + void OnSetSyncVariant(wxCommandEvent& event); + //context menu handler methods void OnContextFilterTemp (wxCommandEvent& event); void OnContextExcludeExtension (wxCommandEvent& event); @@ -182,15 +196,12 @@ private: void OnSaveConfig( wxCommandEvent& event); void OnLoadConfig( wxCommandEvent& event); void OnLoadFromHistory( wxCommandEvent& event); - bool trySaveConfig(); //return true if saved successfully - bool saveOldConfig(); //return false on user abort - void loadConfiguration(const wxString& filename); void OnCfgHistoryKeyEvent( wxKeyEvent& event); void OnRegularUpdateCheck( wxIdleEvent& event); void OnLayoutWindowAsync( wxIdleEvent& event); - void refreshGridAfterFilterChange(const int delay); + void refreshGridAfterFilterChange(int delay); void OnResize( wxSizeEvent& event); //void OnResizeTopButtons( wxEvent& event); diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp index 949384b9..e244877a 100644 --- a/ui/progress_indicator.cpp +++ b/ui/progress_indicator.cpp @@ -67,7 +67,7 @@ public: void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusPanelNow(); private: @@ -76,7 +76,7 @@ private: //status variables size_t scannedObjects; - Zstring currentStatusText; + wxString currentStatusText; wxStopWatch timeElapsed; @@ -146,7 +146,7 @@ void CompareStatus::incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int6 pimpl->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); } -void CompareStatus::setStatusText_NoUpdate(const Zstring& text) +void CompareStatus::setStatusText_NoUpdate(const wxString& text) { pimpl->setStatusText_NoUpdate(text); } @@ -276,7 +276,7 @@ void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsP } -void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const wxString& text) { currentStatusText = text; } @@ -334,10 +334,8 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() bool updateLayout = false; //avoid screen flicker by calling layout() only if necessary //remove linebreaks from currentStatusText - wxString formattedStatusText = zToWx(currentStatusText); - for (wxString::iterator i = formattedStatusText.begin(); i != formattedStatusText.end(); ++i) - if (*i == wxChar('\n')) - *i = wxChar(' '); + wxString formattedStatusText = currentStatusText; + replace(formattedStatusText, L'\n', L' '); //status texts if (m_textCtrlStatus->GetValue() != formattedStatusText) //no layout update for status texts! @@ -490,7 +488,7 @@ public: void resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); void incScannedObjects_NoUpdate(int number); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusDialogNow(); void setCurrentStatus(SyncStatus::SyncStatusID id); @@ -525,7 +523,7 @@ private: //status variables size_t scannedObjects; - Zstring currentStatusText; + wxString currentStatusText; bool processPaused; SyncStatus::SyncStatusID currentStatus; @@ -596,7 +594,7 @@ void SyncStatus::incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 pimpl->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); } -void SyncStatus::setStatusText_NoUpdate(const Zstring& text) +void SyncStatus::setStatusText_NoUpdate(const wxString& text) { pimpl->setStatusText_NoUpdate(text); } @@ -661,14 +659,14 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, m_gauge1->SetRange(GAUGE_FULL_RANGE); m_gauge1->SetValue(0); + + EnableCloseButton(false); + if (IsShown()) //don't steal focus when starting in sys-tray! m_buttonAbort->SetFocus(); if (mainDialog) - { - mainDialog->EnableCloseButton(false); mainDialog->disableAllElements(false); //disable all child elements - } timeElapsed.Start(); //measure total time @@ -697,7 +695,6 @@ SyncStatus::SyncStatusImpl::~SyncStatusImpl() { if (mainDialog) { - mainDialog->EnableCloseButton(true); mainDialog->enableAllElements(); //restore title text @@ -716,7 +713,21 @@ void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) - Close(); //generate close event: do NOT destroy window unconditionally! + { + wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); + + //simulate click on abort button + if (m_buttonAbort->IsShown()) //delegate to "abort" button if available + { + m_buttonAbort->GetEventHandler()->ProcessEvent(dummy); + return; + } + else if (m_buttonOK->IsShown()) //delegate to "abort" button if available + { + m_buttonOK->GetEventHandler()->ProcessEvent(dummy); + return; + } + } event.Skip(); } @@ -762,7 +773,7 @@ void SyncStatus::SyncStatusImpl::incScannedObjects_NoUpdate(int number) } -void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const wxString& text) { currentStatusText = text; } @@ -833,7 +844,7 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow() //static RetrieveStatistics statistic; //statistic.writeEntry(currentData.ToDouble(), currentObjects); - const float percent = totalData == 0 ? 0 : to<double>(currentData) * 100.0 / to<double>(totalData); + const float percent = totalData == 0 ? 100.0 : to<double>(currentData) * 100.0 / to<double>(totalData); //write status information to systray, taskbar, parent title ect. @@ -886,9 +897,8 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow() } //status text - const wxString statusTxt = zToWx(currentStatusText); - if (m_textCtrlInfo->GetValue() != statusTxt) //no layout update for status texts! - m_textCtrlInfo->ChangeValue(statusTxt); + if (m_textCtrlInfo->GetValue() != currentStatusText) //no layout update for status texts! + m_textCtrlInfo->ChangeValue(currentStatusText); //remaining objects const wxString remainingObjTmp = toStringSep(totalObjects - currentObjects); @@ -1016,6 +1026,8 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, resumeFromSystray(); //if in tray mode... + EnableCloseButton(true); + m_buttonAbort->Disable(); m_buttonAbort->Hide(); m_buttonPause->Disable(); @@ -1074,7 +1086,7 @@ void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event) m_buttonPause->Disable(); m_buttonPause->Hide(); - setStatusText_NoUpdate(wxToZ(_("Abort requested: Waiting for current operation to finish..."))); + setStatusText_NoUpdate(_("Abort requested: Waiting for current operation to finish...")); //no Layout() or UI-update here to avoid cascaded Yield()-call abortCb_->requestAbortion(); @@ -1114,17 +1126,11 @@ void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event) void SyncStatus::SyncStatusImpl::OnClose(wxCloseEvent& event) { - if (m_buttonAbort->IsShown()) //delegate to "abort" button if available - { - wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); - m_buttonAbort->GetEventHandler()->ProcessEvent(dummy); - - if (event.CanVeto()) - { - event.Veto(); //that's what we want here - return; - } - } + //this event handler may be called due to a system shutdown DURING synchronization! + //try to stop sync gracefully and cross fingers: + if (currentProcessIsRunning()) + abortCb_->requestAbortion(); + //Note: we must NOT veto dialog destruction, else we will cancel system shutdown if this dialog is application main window (like in batch mode) Destroy(); } diff --git a/ui/progress_indicator.h b/ui/progress_indicator.h index 528ec562..9bb0eed0 100644 --- a/ui/progress_indicator.h +++ b/ui/progress_indicator.h @@ -32,7 +32,7 @@ public: void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusPanelNow(); private: @@ -67,7 +67,7 @@ public: void resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusDialogNow(); void setCurrentStatus(SyncStatusID id); diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp index f6694586..ed28a166 100644 --- a/ui/small_dlgs.cpp +++ b/ui/small_dlgs.cpp @@ -296,8 +296,8 @@ void FilterDlg::updateGui() void FilterDlg::setFilter(const FilterConfig& filter) { - m_textCtrlInclude->ChangeValue(zToWx(filter.includeFilter)); - m_textCtrlExclude->ChangeValue(zToWx(filter.excludeFilter)); + m_textCtrlInclude->ChangeValue(toWx(filter.includeFilter)); + m_textCtrlExclude->ChangeValue(toWx(filter.excludeFilter)); setEnumVal(enumTimeDescr, *m_choiceUnitTimespan, filter.unitTimeSpan); setEnumVal(enumSizeDescr, *m_choiceUnitMinSize, filter.unitSizeMin); @@ -313,8 +313,8 @@ void FilterDlg::setFilter(const FilterConfig& filter) FilterConfig FilterDlg::getFilter() const { - return FilterConfig(wxToZ(m_textCtrlInclude->GetValue()), - wxToZ(m_textCtrlExclude->GetValue()), + return FilterConfig(toZ(m_textCtrlInclude->GetValue()), + toZ(m_textCtrlExclude->GetValue()), m_spinCtrlTimespan->GetValue(), getEnumVal(enumTimeDescr, *m_choiceUnitTimespan), m_spinCtrlMinSize->GetValue(), @@ -458,7 +458,7 @@ void DeleteDialog::updateGui() header.Replace(wxT("%x"), toStringSep(delInfo.second)); m_staticTextHeader->SetLabel(header); - const wxString filesToDelete = delInfo.first; + const wxString& filesToDelete = delInfo.first; m_textCtrlMessage->SetValue(filesToDelete); Layout(); @@ -733,71 +733,29 @@ class CompareCfgDialog : public CmpCfgDlgGenerated { public: CompareCfgDialog(wxWindow* parent, - const wxPoint& position, zen::CompareVariant& cmpVar, SymLinkHandling& handleSymlinks); private: void OnOkay(wxCommandEvent& event); - void OnClose(wxCloseEvent& event); - void OnCancel(wxCommandEvent& event); + void OnClose(wxCloseEvent& event) { EndModal(0); } + void OnCancel(wxCommandEvent& event) { EndModal(0); } void OnTimeSize(wxCommandEvent& event); + void OnTimeSizeDouble(wxMouseEvent& event); void OnContent(wxCommandEvent& event); + void OnContentDouble(wxMouseEvent& event); void OnShowHelp(wxCommandEvent& event); void updateView(); zen::CompareVariant& cmpVarOut; SymLinkHandling& handleSymlinksOut; -}; - -namespace -{ -void setValue(wxChoice& choiceCtrl, zen::SymLinkHandling value) -{ - choiceCtrl.Clear(); - choiceCtrl.Append(_("Ignore")); - choiceCtrl.Append(_("Direct")); - choiceCtrl.Append(_("Follow")); - - //default - choiceCtrl.SetSelection(0); - - switch (value) - { - case zen::SYMLINK_IGNORE: - choiceCtrl.SetSelection(0); - break; - case zen::SYMLINK_USE_DIRECTLY: - choiceCtrl.SetSelection(1); - break; - case zen::SYMLINK_FOLLOW_LINK: - choiceCtrl.SetSelection(2); - break; - } -} + zen::EnumDescrList<SymLinkHandling> enumDescrHandleSyml; +}; -zen::SymLinkHandling getValue(const wxChoice& choiceCtrl) -{ - switch (choiceCtrl.GetSelection()) - { - case 0: - return zen::SYMLINK_IGNORE; - case 1: - return zen::SYMLINK_USE_DIRECTLY; - case 2: - return zen::SYMLINK_FOLLOW_LINK; - default: - assert(false); - return zen::SYMLINK_IGNORE; - } -} -} - CompareCfgDialog::CompareCfgDialog(wxWindow* parent, - const wxPoint& position, CompareVariant& cmpVar, SymLinkHandling& handleSymlinks) : CmpCfgDlgGenerated(parent), @@ -808,8 +766,13 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent, new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" #endif + enumDescrHandleSyml. + add(SYMLINK_IGNORE, _("Ignore")). + add(SYMLINK_USE_DIRECTLY, _("Direct")). + add(SYMLINK_FOLLOW_LINK, _("Follow")); + //move dialog up so that compare-config button and first config-variant are on same level - Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); + // Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); m_bpButtonHelp ->SetBitmapLabel(GlobalResources::instance().getImage(wxT("help"))); m_bitmapByTime ->SetBitmap (GlobalResources::instance().getImage(wxT("clock"))); @@ -827,8 +790,7 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent, break; } - - setValue(*m_choiceHandleSymlinks, handleSymlinks); + setEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks, handleSymlinks); updateView(); } @@ -845,35 +807,37 @@ void CompareCfgDialog::OnOkay(wxCommandEvent& event) else cmpVarOut = CMP_BY_TIME_SIZE; - handleSymlinksOut = getValue(*m_choiceHandleSymlinks);; + handleSymlinksOut = getEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks); EndModal(ReturnSmallDlg::BUTTON_OKAY); } -void CompareCfgDialog::OnClose(wxCloseEvent& event) +void CompareCfgDialog::OnTimeSize(wxCommandEvent& event) { - EndModal(0); + m_radioBtnSizeDate->SetValue(true); } -void CompareCfgDialog::OnCancel(wxCommandEvent& event) +void CompareCfgDialog::OnContent(wxCommandEvent& event) { - EndModal(0); + m_radioBtnContent->SetValue(true); } -void CompareCfgDialog::OnTimeSize(wxCommandEvent& event) +void CompareCfgDialog::OnTimeSizeDouble(wxMouseEvent& event) { - m_radioBtnSizeDate->SetValue(true); - OnOkay(event); + wxCommandEvent dummy; + OnTimeSize(dummy); + OnOkay(dummy); } -void CompareCfgDialog::OnContent(wxCommandEvent& event) +void CompareCfgDialog::OnContentDouble(wxMouseEvent& event) { - m_radioBtnContent->SetValue(true); - OnOkay(event); + wxCommandEvent dummy; + OnContent(dummy); + OnOkay(dummy); } @@ -884,12 +848,10 @@ void CompareCfgDialog::OnShowHelp(wxCommandEvent& event) } -ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog( - const wxPoint& position, - CompareVariant& cmpVar, - SymLinkHandling& handleSymlinks) +ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog(CompareVariant& cmpVar, + SymLinkHandling& handleSymlinks) { - CompareCfgDialog syncDlg(NULL, position, cmpVar, handleSymlinks); + CompareCfgDialog syncDlg(NULL, cmpVar, handleSymlinks); return static_cast<ReturnSmallDlg::ButtonPressed>(syncDlg.ShowModal()); } diff --git a/ui/small_dlgs.h b/ui/small_dlgs.h index 06fb9964..31fd4548 100644 --- a/ui/small_dlgs.h +++ b/ui/small_dlgs.h @@ -43,7 +43,6 @@ ReturnSmallDlg::ButtonPressed showSyncPreviewDlg( bool& dontShowAgain); ReturnSmallDlg::ButtonPressed showCompareCfgDialog( - const wxPoint& position, CompareVariant& cmpVar, SymLinkHandling& handleSymlinks); diff --git a/ui/sorting.h b/ui/sorting.h index 28f0b8e4..d2bafd1d 100644 --- a/ui/sorting.h +++ b/ui/sorting.h @@ -8,7 +8,6 @@ #define SORTING_H_INCLUDED #include "../file_hierarchy.h" -#include "../shared/system_constants.h" #include "../synchronization.h" #include "../shared/assert_static.h" diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp index 0bbe8809..59d4d689 100644 --- a/ui/sync_cfg.cpp +++ b/ui/sync_cfg.cpp @@ -40,6 +40,11 @@ private: virtual void OnSyncUpdate( wxCommandEvent& event); virtual void OnSyncCustom( wxCommandEvent& event); + virtual void OnSyncAutomaticDouble( wxMouseEvent& event); + virtual void OnSyncMirrorDouble( wxMouseEvent& event); + virtual void OnSyncUpdateDouble( wxMouseEvent& event); + virtual void OnSyncCustomDouble( wxMouseEvent& event); + virtual void OnExLeftSideOnly( wxCommandEvent& event); virtual void OnExRightSideOnly( wxCommandEvent& event); virtual void OnLeftNewer( wxCommandEvent& event); @@ -47,8 +52,8 @@ private: virtual void OnDifferent( wxCommandEvent& event); virtual void OnConflict( wxCommandEvent& event); - virtual void OnClose( wxCloseEvent& event); - virtual void OnCancel( wxCommandEvent& event); + virtual void OnClose( wxCloseEvent& event) { EndModal(0); } + virtual void OnCancel( wxCommandEvent& event) { EndModal(0); } virtual void OnApply( wxCommandEvent& event); void updateGui(); @@ -332,18 +337,6 @@ void SyncCfgDialog::updateGui() } -void SyncCfgDialog::OnClose(wxCloseEvent& event) -{ - EndModal(0); -} - - -void SyncCfgDialog::OnCancel(wxCommandEvent& event) -{ - EndModal(0); -} - - void SyncCfgDialog::OnApply(wxCommandEvent& event) { //write configuration to main dialog @@ -399,6 +392,35 @@ void SyncCfgDialog::OnSyncCustom(wxCommandEvent& event) } +void SyncCfgDialog::OnSyncAutomaticDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncAutomatic(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncMirrorDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncMirror(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncUpdateDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncUpdate(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncCustomDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncCustom(dummy); + OnApply(dummy); +} + + void toggleSyncDirection(SyncDirection& current) { switch (current) diff --git a/version.h b/version.h deleted file mode 100644 index 352e718f..00000000 --- a/version.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -namespace AutoVersion -{ - -//Date Version Types -static const char DATE[] = "21"; -static const char MONTH[] = "05"; -static const char YEAR[] = "2011"; -static const char UBUNTU_VERSION_STYLE[] = "11.05"; - -//Software Status -static const char STATUS[] = "Alpha"; -static const char STATUS_SHORT[] = "a"; - -//Standard Version Type -static const long MAJOR = 1; -static const long MINOR = 0; -static const long BUILD = 0; -static const long REVISION = 0; - -//Miscellaneous Version Types -static const long BUILDS_COUNT = 1; -#define RC_FILEVERSION 1,0,0,0 -#define RC_FILEVERSION_STRING "1, 0, 0, 0\0" -static const char FULLVERSION_STRING[] = "1.0.0.0"; - -//These values are to keep track of your versioning state, don't modify them. -static const long BUILD_HISTORY = 0; - - -} -#endif //VERSION_H diff --git a/version/version.h b/version/version.h index 93796a2a..16eeb18d 100644 --- a/version/version.h +++ b/version/version.h @@ -2,5 +2,5 @@ namespace zen { -const wxString currentVersion = wxT("3.18"); //internal linkage! +const wxString currentVersion = wxT("3.19"); //internal linkage! } diff --git a/version/version.rc b/version/version.rc index 4b728f25..fd3faf30 100644 --- a/version/version.rc +++ b/version/version.rc @@ -1,2 +1,2 @@ -#define VER_FREEFILESYNC 3,18,0,0 -#define VER_FREEFILESYNC_STR "3.18\0" +#define VER_FREEFILESYNC 3,19,0,0 +#define VER_FREEFILESYNC_STR "3.19\0" |