summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/IFileOperation/dll_main.cpp2
-rw-r--r--shared/IFileOperation/file_op.cpp2
-rw-r--r--shared/IFileOperation/file_op.h2
-rw-r--r--shared/ShadowCopy/LockFile.cpp2
-rw-r--r--shared/ShadowCopy/dll_main.cpp2
-rw-r--r--shared/ShadowCopy/shadow.cpp2
-rw-r--r--shared/ShadowCopy/shadow.h2
-rw-r--r--shared/Taskbar_Seven/dll_main.cpp2
-rw-r--r--shared/Taskbar_Seven/taskbar.cpp2
-rw-r--r--shared/Taskbar_Seven/taskbar.h2
-rw-r--r--shared/app_main.cpp2
-rw-r--r--shared/app_main.h2
-rw-r--r--shared/build_info.h2
-rw-r--r--shared/c_dll.h2
-rw-r--r--shared/check_exist.cpp58
-rw-r--r--shared/check_exist.h71
-rw-r--r--shared/com_error.h2
-rw-r--r--shared/com_ptr.h2
-rw-r--r--shared/com_util.h2
-rw-r--r--shared/custom_button.cpp2
-rw-r--r--shared/custom_button.h2
-rw-r--r--shared/custom_combo_box.cpp2
-rw-r--r--shared/custom_combo_box.h2
-rw-r--r--shared/custom_tooltip.cpp2
-rw-r--r--shared/custom_tooltip.h2
-rw-r--r--shared/debug_log.h2
-rw-r--r--shared/debug_new.cpp2
-rw-r--r--shared/debug_new.h2
-rw-r--r--shared/dir_name.cpp5
-rw-r--r--shared/dir_name.h2
-rw-r--r--shared/dir_watcher.cpp31
-rw-r--r--shared/dir_watcher.h2
-rw-r--r--shared/dll_loader.cpp2
-rw-r--r--shared/dll_loader.h4
-rw-r--r--shared/dst_hack.cpp6
-rw-r--r--shared/file_drop.h2
-rw-r--r--shared/file_error.h4
-rw-r--r--shared/file_handling.cpp287
-rw-r--r--shared/file_handling.h14
-rw-r--r--shared/file_id.cpp5
-rw-r--r--shared/file_id.h2
-rw-r--r--shared/file_io.cpp2
-rw-r--r--shared/file_io.h2
-rw-r--r--shared/file_traverser.cpp56
-rw-r--r--shared/file_traverser.h2
-rw-r--r--shared/file_update_handle.h67
-rw-r--r--shared/global_func.h2
-rw-r--r--shared/guid.cpp2
-rw-r--r--shared/guid.h2
-rw-r--r--shared/help_provider.cpp2
-rw-r--r--shared/help_provider.h2
-rw-r--r--shared/i18n.h2
-rw-r--r--shared/int64.h2
-rw-r--r--shared/last_error.cpp2
-rw-r--r--shared/last_error.h2
-rw-r--r--shared/localization.cpp2
-rw-r--r--shared/localization.h2
-rw-r--r--shared/long_path_prefix.h2
-rw-r--r--shared/mouse_move_dlg.cpp2
-rw-r--r--shared/mouse_move_dlg.h2
-rw-r--r--shared/notify_removal.cpp6
-rw-r--r--shared/notify_removal.h2
-rw-r--r--shared/parse_lng.h2
-rw-r--r--shared/parse_plural.h2
-rw-r--r--shared/parse_txt.h2
-rw-r--r--shared/pch.h2
-rw-r--r--shared/perf.h2
-rw-r--r--shared/recycler.cpp92
-rw-r--r--shared/recycler.h15
-rw-r--r--shared/resolve_path.cpp47
-rw-r--r--shared/resolve_path.h2
-rw-r--r--shared/serialize.cpp2
-rw-r--r--shared/serialize.h2
-rw-r--r--shared/shadow.cpp29
-rw-r--r--shared/shadow.h2
-rw-r--r--shared/shell_execute.h32
-rw-r--r--shared/standard_paths.cpp2
-rw-r--r--shared/standard_paths.h2
-rw-r--r--shared/string_conv.h2
-rw-r--r--shared/symlink_target.h2
-rw-r--r--shared/taskbar.cpp106
-rw-r--r--shared/taskbar.h22
-rw-r--r--shared/toggle_button.cpp2
-rw-r--r--shared/toggle_button.h2
-rw-r--r--shared/util.cpp2
-rw-r--r--shared/util.h2
-rw-r--r--shared/warn_static.h35
-rw-r--r--shared/wx_choice_enum.h2
-rw-r--r--shared/wx_timespan.h2
-rw-r--r--shared/xml_base.cpp7
-rw-r--r--shared/xml_base.h2
-rw-r--r--shared/xml_error.h2
-rw-r--r--shared/zbase.h68
-rw-r--r--shared/zstring.cpp14
-rw-r--r--shared/zstring.h16
95 files changed, 704 insertions, 533 deletions
diff --git a/shared/IFileOperation/dll_main.cpp b/shared/IFileOperation/dll_main.cpp
index ab387012..3805c99d 100644
--- a/shared/IFileOperation/dll_main.cpp
+++ b/shared/IFileOperation/dll_main.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/shared/IFileOperation/file_op.cpp b/shared/IFileOperation/file_op.cpp
index fc942f44..a2cf9413 100644
--- a/shared/IFileOperation/file_op.cpp
+++ b/shared/IFileOperation/file_op.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_op.h"
#include "../com_ptr.h"
#include "../com_error.h"
diff --git a/shared/IFileOperation/file_op.h b/shared/IFileOperation/file_op.h
index 25098e45..c1bb26a2 100644
--- a/shared/IFileOperation/file_op.h
+++ b/shared/IFileOperation/file_op.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef RECYCLER_DLL_H
#define RECYCLER_DLL_H
diff --git a/shared/ShadowCopy/LockFile.cpp b/shared/ShadowCopy/LockFile.cpp
index 0761a3e3..7df3ec66 100644
--- a/shared/ShadowCopy/LockFile.cpp
+++ b/shared/ShadowCopy/LockFile.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include <string>
#include <iostream>
diff --git a/shared/ShadowCopy/dll_main.cpp b/shared/ShadowCopy/dll_main.cpp
index ab387012..3805c99d 100644
--- a/shared/ShadowCopy/dll_main.cpp
+++ b/shared/ShadowCopy/dll_main.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/shared/ShadowCopy/shadow.cpp b/shared/ShadowCopy/shadow.cpp
index d536470a..8b7b9971 100644
--- a/shared/ShadowCopy/shadow.cpp
+++ b/shared/ShadowCopy/shadow.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "shadow.h"
#include <algorithm>
#include <string>
diff --git a/shared/ShadowCopy/shadow.h b/shared/ShadowCopy/shadow.h
index a96d8578..b21395da 100644
--- a/shared/ShadowCopy/shadow.h
+++ b/shared/ShadowCopy/shadow.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SHADOWCOPY_H
#define SHADOWCOPY_H
diff --git a/shared/Taskbar_Seven/dll_main.cpp b/shared/Taskbar_Seven/dll_main.cpp
index ab387012..3805c99d 100644
--- a/shared/Taskbar_Seven/dll_main.cpp
+++ b/shared/Taskbar_Seven/dll_main.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/shared/Taskbar_Seven/taskbar.cpp b/shared/Taskbar_Seven/taskbar.cpp
index 297a0739..bbbaaf7d 100644
--- a/shared/Taskbar_Seven/taskbar.cpp
+++ b/shared/Taskbar_Seven/taskbar.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "taskbar.h"
#define WIN32_LEAN_AND_MEAN
diff --git a/shared/Taskbar_Seven/taskbar.h b/shared/Taskbar_Seven/taskbar.h
index d52420ab..3bae28a9 100644
--- a/shared/Taskbar_Seven/taskbar.h
+++ b/shared/Taskbar_Seven/taskbar.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef TASKBAR_SEVEN_DLL_H
#define TASKBAR_SEVEN_DLL_H
diff --git a/shared/app_main.cpp b/shared/app_main.cpp
index b727724f..28ce1e09 100644
--- a/shared/app_main.cpp
+++ b/shared/app_main.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "app_main.h"
#include <wx/window.h>
#include <wx/app.h>
diff --git a/shared/app_main.h b/shared/app_main.h
index 33ddcfb6..fa538771 100644
--- a/shared/app_main.h
+++ b/shared/app_main.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef APPMAIN_H_INCLUDED
#define APPMAIN_H_INCLUDED
diff --git a/shared/build_info.h b/shared/build_info.h
index c3be26bd..f13b2dbc 100644
--- a/shared/build_info.h
+++ b/shared/build_info.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef BUILDINFO_H_INCLUDED
#define BUILDINFO_H_INCLUDED
diff --git a/shared/c_dll.h b/shared/c_dll.h
index f913cde9..15597a9c 100644
--- a/shared/c_dll.h
+++ b/shared/c_dll.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef C_DLL_HEADER
#define C_DLL_HEADER
diff --git a/shared/check_exist.cpp b/shared/check_exist.cpp
deleted file mode 100644
index 6c6c0871..00000000
--- a/shared/check_exist.cpp
+++ /dev/null
@@ -1,58 +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 "check_exist.h"
-#include "file_handling.h"
-#include <memory>
-#include "boost_thread_wrap.h" //include <boost/thread.hpp>
-
-
-/*
-#ifdef __MINGW32__
-//oh well, nothing is for free...
-//https://svn.boost.org/trac/boost/ticket/4258
-extern "C" void tss_cleanup_implemented() {};
-#endif
-*/
-
-namespace
-{
-typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class
-
-template <bool (*fun)(const Zstring&)>
-util::ResultExist checkExistence(const Zstring& objName, size_t timeout) //timeout in ms
-{
- using namespace util;
-
- std::shared_ptr<bool> isExisting = std::make_shared<bool>(false); //no mutex required: accessed after thread has finished only!
- BasicString filename = objName.c_str(); //using thread safe string without ref-count!
-
- boost::thread worker([=]() { *isExisting = fun(filename.c_str()); }); //throw()
-
- if (worker.timed_join(boost::posix_time::milliseconds(timeout)))
- return *isExisting ? EXISTING_TRUE : EXISTING_FALSE;
- else
- return EXISTING_TIMEOUT;
- /*
- main/worker thread may access different shared_ptr instances safely (even though they have the same target!)
- http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm?sess=8153b05b34d890e02d48730db1ff7ddc#ThreadSafety
- */
-}
-}
-
-
-util::ResultExist util::fileExists(const Zstring& filename, size_t timeout) //timeout in ms
-{
- assert(!filename.empty());
- return ::checkExistence<zen::fileExists>(filename, timeout);
-}
-
-
-util::ResultExist util::dirExists(const Zstring& dirname, size_t timeout) //timeout in ms
-{
- assert(!dirname.empty());
- return ::checkExistence<zen::dirExists>(dirname, timeout);
-}
diff --git a/shared/check_exist.h b/shared/check_exist.h
index 6ec5534c..14a8a3f8 100644
--- a/shared/check_exist.h
+++ b/shared/check_exist.h
@@ -3,23 +3,86 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef CHECKEXIST_H_INCLUDED
#define CHECKEXIST_H_INCLUDED
#include "zstring.h"
+#include "boost_thread_wrap.h" //include <boost/thread.hpp>
+#include "file_handling.h"
+
namespace util
{
+//check for file or folder existence asynchronously
+boost::unique_future<bool> somethingExistsAsync(const Zstring& somename);
+boost::unique_future<bool> fileExistsAsync(const Zstring& filename);
+boost::unique_future<bool> dirExistsAsync(const Zstring& dirname);
+
+//some syntactic sugar:
enum ResultExist
{
EXISTING_TRUE,
EXISTING_FALSE,
- EXISTING_TIMEOUT
+ EXISTING_NOT_READY
};
-ResultExist fileExists(const Zstring& filename, size_t timeout); //timeout in ms
-ResultExist dirExists( const Zstring& dirname, size_t timeout); //timeout in ms
+ResultExist somethingExists(const Zstring& somename, size_t timeout);
+ResultExist fileExists(const Zstring& filename, size_t timeout);
+ResultExist dirExists(const Zstring& dirname, size_t timeout);
+
+
+
+
+
+
+
+
+
+
+
+
+//################## implementation ##########################
+template <bool (*fun)(const Zstring&)>
+boost::unique_future<bool> objExistsAsync(const Zstring& objname)
+{
+ //thread safety: make it a pure value type for use in the thread!
+ const Zstring objnameVal = objname; //atomic ref-count => binary value-type semantics!
+ boost::packaged_task<bool> pt([=] { return (*fun)(objnameVal); });
+ auto fut = pt.get_future();
+ boost::thread(std::move(pt));
+ return std::move(fut);
+}
+
+
+inline
+boost::unique_future<bool> somethingExistsAsync(const Zstring& somename) { return objExistsAsync<&zen::somethingExists>(somename); }
+
+inline
+boost::unique_future<bool> fileExistsAsync(const Zstring& filename) { return objExistsAsync<&zen::fileExists>(filename); }
+
+inline
+boost::unique_future<bool> dirExistsAsync(const Zstring& dirname) { return objExistsAsync<&zen::dirExists>(dirname); }
+
+
+template <bool (*fun)(const Zstring&)> inline
+ResultExist objExists(const Zstring& objname, size_t timeout)
+{
+ auto ft = objExistsAsync<fun>(objname);
+ if (!ft.timed_wait(boost::posix_time::milliseconds(timeout)))
+ return EXISTING_NOT_READY;
+ return ft.get() ? EXISTING_TRUE : EXISTING_FALSE;
+}
+
+
+inline
+ResultExist somethingExists(const Zstring& somename, size_t timeout) { return objExists<&zen::somethingExists>(somename, timeout); }
+
+inline
+ResultExist fileExists(const Zstring& filename, size_t timeout) { return objExists<&zen::fileExists>(filename, timeout); }
+
+inline
+ResultExist dirExists(const Zstring& dirname, size_t timeout) { return objExists<&zen::dirExists>(dirname, timeout); }
}
#endif // CHECKEXIST_H_INCLUDED
diff --git a/shared/com_error.h b/shared/com_error.h
index 909e04c1..39f26555 100644
--- a/shared/com_error.h
+++ b/shared/com_error.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef COM_ERROR_HEADER
#define COM_ERROR_HEADER
diff --git a/shared/com_ptr.h b/shared/com_ptr.h
index fa1b3e8f..be1776fd 100644
--- a/shared/com_ptr.h
+++ b/shared/com_ptr.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SMART_COM_PTR_H
#define SMART_COM_PTR_H
diff --git a/shared/com_util.h b/shared/com_util.h
index 4a8c4f54..b8fc777d 100644
--- a/shared/com_util.h
+++ b/shared/com_util.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef COM_UTILITY_HEADER
#define COM_UTILITY_HEADER
diff --git a/shared/custom_button.cpp b/shared/custom_button.cpp
index 98c0a3cd..0c4c3019 100644
--- a/shared/custom_button.cpp
+++ b/shared/custom_button.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "custom_button.h"
#include <wx/dcmemory.h>
#include <wx/image.h>
diff --git a/shared/custom_button.h b/shared/custom_button.h
index 752c763e..8500e59b 100644
--- a/shared/custom_button.h
+++ b/shared/custom_button.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef CUSTOMBUTTON_H_INCLUDED
#define CUSTOMBUTTON_H_INCLUDED
diff --git a/shared/custom_combo_box.cpp b/shared/custom_combo_box.cpp
index f6084fdf..fb16a303 100644
--- a/shared/custom_combo_box.cpp
+++ b/shared/custom_combo_box.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "custom_combo_box.h"
diff --git a/shared/custom_combo_box.h b/shared/custom_combo_box.h
index 070790a6..3ddd73b0 100644
--- a/shared/custom_combo_box.h
+++ b/shared/custom_combo_box.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef CUSTOMCOMBOBOX_H_INCLUDED
#define CUSTOMCOMBOBOX_H_INCLUDED
diff --git a/shared/custom_tooltip.cpp b/shared/custom_tooltip.cpp
index f19f3822..184c2716 100644
--- a/shared/custom_tooltip.cpp
+++ b/shared/custom_tooltip.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "custom_tooltip.h"
#include <wx/stattext.h>
#include <wx/sizer.h>
diff --git a/shared/custom_tooltip.h b/shared/custom_tooltip.h
index c5cb132b..c68856b4 100644
--- a/shared/custom_tooltip.h
+++ b/shared/custom_tooltip.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef CUSTOMTOOLTIP_H_INCLUDED
#define CUSTOMTOOLTIP_H_INCLUDED
diff --git a/shared/debug_log.h b/shared/debug_log.h
index 8e8090f0..561eee9d 100644
--- a/shared/debug_log.h
+++ b/shared/debug_log.h
@@ -3,7 +3,7 @@
// * 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
diff --git a/shared/debug_new.cpp b/shared/debug_new.cpp
index a7324239..23a26a4e 100644
--- a/shared/debug_new.cpp
+++ b/shared/debug_new.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "debug_new.h"
#ifdef _MSC_VER
diff --git a/shared/debug_new.h b/shared/debug_new.h
index afa66a55..b8911b4d 100644
--- a/shared/debug_new.h
+++ b/shared/debug_new.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef DEBUGNEW_H_INCLUDED
#define DEBUGNEW_H_INCLUDED
diff --git a/shared/dir_name.cpp b/shared/dir_name.cpp
index 6566bb3a..6945fb9c 100644
--- a/shared/dir_name.cpp
+++ b/shared/dir_name.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "dir_name.h"
#include <wx/dnd.h>
#include <wx/window.h>
@@ -40,7 +40,8 @@ void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, w
if (dirPicker)
{
- if (!dirFormatted.empty() && util::dirExists(toZ(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);
}
}
diff --git a/shared/dir_name.h b/shared/dir_name.h
index 4bf07231..6e783d75 100644
--- a/shared/dir_name.h
+++ b/shared/dir_name.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef DRAGANDDROP_H_INCLUDED
#define DRAGANDDROP_H_INCLUDED
diff --git a/shared/dir_watcher.cpp b/shared/dir_watcher.cpp
index 8e0b7f94..9c3a00c7 100644
--- a/shared/dir_watcher.cpp
+++ b/shared/dir_watcher.cpp
@@ -3,7 +3,7 @@
// * 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"
@@ -32,23 +32,22 @@ 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
+typedef Zbase<wchar_t> BasicWString; //thread safe string class for UI texts
struct SharedData
{
boost::mutex lockAccess;
- std::set<BasicString> changedFiles; //get rid of duplicate entries (actually occur!)
+ std::set<Zstring> 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 ()
+void addChanges(SharedData& shared, const char* buffer, DWORD bytesWritten, const Zstring& dirname) //throw ()
{
boost::lock_guard<boost::mutex> dummy(shared.lockAccess);
- std::set<BasicString>& output = shared.changedFiles;
+ std::set<Zstring>& 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!");
@@ -59,14 +58,14 @@ void addChanges(SharedData& shared, const char* buffer, DWORD bytesWritten, cons
{
const FILE_NOTIFY_INFORMATION& notifyInfo = reinterpret_cast<const FILE_NOTIFY_INFORMATION&>(*bufPos);
- const BasicString fullname = dirname + BasicString(notifyInfo.FileName, notifyInfo.FileNameLength / sizeof(WCHAR));
+ const Zstring fullname = dirname + Zstring(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());
+ const DWORD ret = ::GetFileAttributes(applyLongPathPrefix(fullname).c_str());
bool isDir = ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_DIRECTORY); //returns true for (dir-)symlinks also
skip = isDir;
}
@@ -90,9 +89,7 @@ void getChanges(SharedData& shared, std::vector<Zstring>& output) //throw FileEr
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); });
-
+ output.assign(shared.changedFiles.begin(), shared.changedFiles.end());
shared.changedFiles.clear();
}
@@ -107,7 +104,7 @@ void reportError(SharedData& shared, const BasicWString& errorMsg) //throw ()
class ReadChangesAsync
{
public:
- ReadChangesAsync(const BasicString& directory, //make sure to not leak in thread-unsafe types!
+ ReadChangesAsync(const Zstring& directory, //make sure to not leak in thread-unsafe types!
const std::shared_ptr<SharedData>& shared) :
shared_(shared),
dirname(directory)
@@ -239,7 +236,7 @@ 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!
+ Zstring dirname; //thread safe!
HANDLE hDir;
};
@@ -250,7 +247,7 @@ public:
HandleVolumeRemoval(HANDLE hDir,
boost::thread& worker,
const std::shared_ptr<SharedData>& shared,
- const BasicString& dirname) :
+ const Zstring& dirname) :
NotifyRequestDeviceRemoval(hDir), //throw FileError
worker_(worker),
shared_(shared),
@@ -283,7 +280,7 @@ private:
boost::thread& worker_;
std::shared_ptr<SharedData> shared_;
- BasicString dirname_;
+ Zstring dirname_;
bool removalRequested;
bool operationComplete;
};
@@ -304,8 +301,8 @@ DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError
{
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
+ ReadChangesAsync reader(directory, pimpl_->shared); //throw FileError
+ pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker, pimpl_->shared, directory)); //throw FileError
pimpl_->worker = boost::thread(std::move(reader));
}
diff --git a/shared/dir_watcher.h b/shared/dir_watcher.h
index 572515dc..c2bab1d5 100644
--- a/shared/dir_watcher.h
+++ b/shared/dir_watcher.h
@@ -3,7 +3,7 @@
// * 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
diff --git a/shared/dll_loader.cpp b/shared/dll_loader.cpp
index 029cabc5..4e2c0e65 100644
--- a/shared/dll_loader.cpp
+++ b/shared/dll_loader.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "dll_loader.h"
#include <map>
diff --git a/shared/dll_loader.h b/shared/dll_loader.h
index 3efb0d96..252e7598 100644
--- a/shared/dll_loader.h
+++ b/shared/dll_loader.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef DLLLOADER_H_INCLUDED
#define DLLLOADER_H_INCLUDED
@@ -23,7 +23,7 @@ namespace util
/*
load function from a DLL library, e.g. from kernel32.dll
-NOTE: you're allowed to take a static reference to the return value to optimize performance! :)
+NOTE: you're allowed to take a static reference to the return value! :)
*/
template <typename FunctionType>
FunctionType getDllFun(const std::wstring& libraryName, const std::string& functionName);
diff --git a/shared/dst_hack.cpp b/shared/dst_hack.cpp
index a64df448..d52a335f 100644
--- a/shared/dst_hack.cpp
+++ b/shared/dst_hack.cpp
@@ -28,8 +28,8 @@ Zstring getVolumeName(const Zstring& filename)
// volumePath += FILE_NAME_SEPARATOR;
Zstring nameFmt = removeLongPathPrefix(filename); //throw()
- if (!nameFmt.EndsWith(Zstr("\\")))
- nameFmt += Zstr("\\"); //GetVolumeInformation expects trailing backslash
+ if (!endsWith(nameFmt, FILE_NAME_SEPARATOR))
+ nameFmt += FILE_NAME_SEPARATOR; //GetVolumeInformation expects trailing backslash
if (nameFmt.StartsWith(Zstr("\\\\"))) //UNC path: "\\ComputerName\SharedFolder\"
{
@@ -58,8 +58,6 @@ Zstring getVolumeName(const Zstring& filename)
bool dst::isFatDrive(const Zstring& fileName) //throw()
{
- using namespace zen;
-
const size_t BUFFER_SIZE = MAX_PATH + 1;
wchar_t fsName[BUFFER_SIZE];
diff --git a/shared/file_drop.h b/shared/file_drop.h
index c85d4cbb..8b11ccfb 100644
--- a/shared/file_drop.h
+++ b/shared/file_drop.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILE_DROP_H_INCLUDED
#define FILE_DROP_H_INCLUDED
diff --git a/shared/file_error.h b/shared/file_error.h
index ae9cc83e..d814e05d 100644
--- a/shared/file_error.h
+++ b/shared/file_error.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILEERROR_H_INCLUDED
#define FILEERROR_H_INCLUDED
@@ -35,7 +35,7 @@ DEFINE_NEW_FILE_ERROR(ErrorFileLocked);
-//facilitate usage of std::wstring for error messages:
+//----------- 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); }
diff --git a/shared/file_handling.cpp b/shared/file_handling.cpp
index a5e7fa9f..6b41f4f5 100644
--- a/shared/file_handling.cpp
+++ b/shared/file_handling.cpp
@@ -3,11 +3,10 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_handling.h"
#include <map>
#include <algorithm>
-#include <boost/bind.hpp>
#include <stdexcept>
#include "last_error.h"
#include "file_traverser.h"
@@ -16,6 +15,8 @@
#include "file_io.h"
#include "i18n.h"
#include "assert_static.h"
+#include <boost/thread/tss.hpp>
+#include <boost/thread/once.hpp>
#ifdef FFS_WIN
#include "privilege.h"
@@ -24,6 +25,7 @@
#include "long_path_prefix.h"
#include <Aclapi.h>
#include "dst_hack.h"
+#include "file_update_handle.h"
#elif defined FFS_LINUX
#include <sys/stat.h>
@@ -99,68 +101,10 @@ 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
- const HANDLE hFile = ::CreateFile(zen::applyLongPathPrefix(linkName).c_str(),
+ const HANDLE hFile = ::CreateFile(applyLongPathPrefix(linkName).c_str(),
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@@ -168,28 +112,28 @@ zen::UInt64 getFileSizeSymlink(const Zstring& linkName) //throw (FileError)
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
- throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + getLastErrorFormatted());
Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hFile);
(void)dummy; //silence warning "unused variable"
BY_HANDLE_FILE_INFORMATION fileInfo = {};
if (!::GetFileInformationByHandle(hFile, &fileInfo))
- throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + linkName + "\"" + "\n\n" + getLastErrorFormatted());
- return zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
+ return UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
}
}
#endif
-zen::UInt64 zen::getFilesize(const Zstring& filename) //throw (FileError)
+UInt64 zen::getFilesize(const Zstring& filename) //throw (FileError)
{
#ifdef FFS_WIN
WIN32_FIND_DATA fileInfo = {};
const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(filename).c_str(), &fileInfo);
if (searchHandle == INVALID_HANDLE_VALUE)
- throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted());
::FindClose(searchHandle);
@@ -197,14 +141,14 @@ zen::UInt64 zen::getFilesize(const Zstring& filename) //throw (FileError)
if (isSymbolicLink)
return getFileSizeSymlink(filename); //throw (FileError)
- return zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
+ return UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
#elif defined FFS_LINUX
struct stat fileInfo = {};
if (::stat(filename.c_str(), &fileInfo) != 0) //follow symbolic links
- throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted());
- return zen::UInt64(fileInfo.st_size);
+ return UInt64(fileInfo.st_size);
#endif
}
@@ -214,7 +158,7 @@ namespace
#ifdef FFS_WIN
DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error!
{
- std::vector<wchar_t> buffer(std::max(pathName.size(), static_cast<size_t>(10000)));
+ std::vector<wchar_t> buffer(10000);
//full pathName need not yet exist!
if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName,
@@ -263,14 +207,14 @@ dev_t retrieveVolumeSerial(const Zstring& pathName) //return 0 on error!
}
-zen::ResponseSameVol zen::onSameVolume(const Zstring& folderLeft, const Zstring& folderRight) //throw()
+zen::ResponseSame zen::onSameVolume(const Zstring& folderLeft, const Zstring& folderRight) //throw()
{
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;
+ return IS_SAME_CANT_SAY;
- return serialLeft == serialRight ? VOLUME_SAME : VOLUME_DIFFERENT;
+ return serialLeft == serialRight ? IS_SAME_YES : IS_SAME_NO;
}
@@ -302,12 +246,12 @@ bool zen::removeFile(const Zstring& filename) //throw (FileError);
#endif
//no error situation if file is not existing! manual deletion relies on it!
- //perf: place check in error handling block
+ //perf: check is placed in error handling block
//warning: this call changes error code!!
if (!somethingExists(filename))
return false; //neither file nor any other object (e.g. broken symlink) with that name existing
- throw FileError(_("Error deleting file:") + "\n\"" + filename + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError));
+ throw FileError(_("Error deleting file:") + "\n\"" + filename + "\"" + "\n\n" + getLastErrorFormatted(lastError));
}
return true;
}
@@ -364,7 +308,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw
}
}
- std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError);
+ std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + getLastErrorFormatted(lastError);
if (lastError == ERROR_NOT_SAME_DEVICE)
throw ErrorDifferentVolume(errorMessage);
@@ -379,7 +323,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw
{
const int lastError = errno;
- std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError);
+ std::wstring errorMessage = _("Error moving file:") + "\n\"" + oldName + "\" ->\n\"" + newName + "\"" + "\n\n" + getLastErrorFormatted(lastError);
if (lastError == EXDEV)
throw ErrorDifferentVolume(errorMessage);
@@ -399,7 +343,7 @@ void renameFileInternal(const Zstring& oldName, const Zstring& newName) //throw
template <typename Function>
Zstring getFilenameFmt(const Zstring& filename, Function fun) //throw(); returns empty string on error
{
- const Zstring filenameFmt = zen::applyLongPathPrefix(filename);
+ const Zstring filenameFmt = applyLongPathPrefix(filename);
const DWORD bufferSize = fun(filenameFmt.c_str(), NULL, 0);
if (bufferSize == 0)
@@ -430,11 +374,11 @@ Zstring createTemp8Dot3Name(const Zstring& fileName) //find a unique 8.3 short n
for (int index = 0; index < 100000000; ++index) //filename must be representable by <= 8 characters
{
const Zstring output = pathPrefix + Zstring::fromNumber(index) + Zchar('.') + extension;
- if (!zen::somethingExists(output)) //ensure uniqueness
+ if (!somethingExists(output)) //ensure uniqueness
return output;
}
- 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));
+ throw std::runtime_error(std::string("100000000 files, one for each number, exist in this directory? You're kidding...\n") + utf8CvrtTo<std::string>(pathPrefix));
}
@@ -446,7 +390,7 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw
if (newName.find(FILE_NAME_SEPARATOR) == Zstring::npos)
return false;
- if (zen::somethingExists(newName)) //name OR directory!
+ if (somethingExists(newName)) //name OR directory!
{
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
@@ -467,7 +411,7 @@ bool fix8Dot3NameClash(const Zstring& oldName, const Zstring& newName) //throw
//move already existing short name out of the way for now
renameFileInternal(unrelatedPathLong, parkedTarget); //throw (FileError: ErrorDifferentVolume);
- //DON'T call zen::renameFile() to avoid reentrance!
+ //DON'T call renameFile() to avoid reentrance!
//schedule cleanup; the file system should assign this unrelated file a new (unique) short name
Loki::ScopeGuard guard = Loki::MakeGuard(renameFileInternal, parkedTarget, unrelatedPathLong);//equivalent to Boost.ScopeExit in this case
@@ -508,7 +452,7 @@ public:
virtual void deleteTargetFile(const Zstring& targetFile) { assert(!fileExists(targetFile)); }
- virtual void updateCopyStatus(zen::UInt64 totalBytesTransferred)
+ virtual void updateCopyStatus(UInt64 totalBytesTransferred)
{
moveCallback.requestUiRefresh(sourceFile_);
}
@@ -665,7 +609,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
//move files
for (TraverseOneLevel::NameList::const_iterator i = fileList.begin(); i != fileList.end(); ++i)
- zen::moveFile(i->second, targetDirFormatted + i->first, ignoreExisting, callback); //throw (FileError: ErrorTargetExisting);
+ moveFile(i->second, targetDirFormatted + i->first, ignoreExisting, callback); //throw (FileError: ErrorTargetExisting);
//move directories
for (TraverseOneLevel::NameList::const_iterator i = dirList.begin(); i != dirList.end(); ++i)
@@ -753,7 +697,7 @@ void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback)
#elif defined FFS_LINUX
if (::unlink(directory.c_str()) != 0)
#endif
- throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + getLastErrorFormatted());
if (callback) callback->notifyDeletion(directory); //once per symlink
return;
@@ -764,7 +708,7 @@ void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback)
//get all files and directories from current directory (WITHOUT subdirectories!)
FilesDirsOnlyTraverser traverser(fileList, dirList);
- zen::traverseFolder(directory, false, traverser); //don't follow symlinks
+ traverseFolder(directory, false, traverser); //don't follow symlinks
//delete files
for (std::vector<Zstring>::const_iterator i = fileList.begin(); i != fileList.end(); ++i)
@@ -784,7 +728,7 @@ void zen::removeDirectory(const Zstring& directory, CallbackRemoveDir* callback)
if (::rmdir(directory.c_str()) != 0)
#endif
{
- throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error deleting directory:") + "\n\"" + directory + "\"" + "\n\n" + getLastErrorFormatted());
}
if (callback) callback->notifyDeletion(directory); //and once per folder
}
@@ -801,7 +745,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
- throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + getLastErrorFormatted());
const bool isReparsePoint = (sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
const bool isDirectory = (sourceAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
@@ -816,7 +760,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)
- throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + getLastErrorFormatted());
Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hSource);
(void)dummy; //silence warning "unused variable"
@@ -825,7 +769,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
- throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + getLastErrorFormatted());
}
else
{
@@ -884,7 +828,7 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool
});
if (targetHandle.get() == INVALID_HANDLE_VALUE)
- throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + getLastErrorFormatted());
/*
if (hTarget == INVALID_HANDLE_VALUE && ::GetLastError() == ERROR_SHARING_VIOLATION)
@@ -898,10 +842,10 @@ void zen::copyFileTimes(const Zstring& sourceObj, const Zstring& targetObj, bool
&creationTime,
NULL,
&lastWriteTime))
- throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + getLastErrorFormatted());
#ifndef NDEBUG //dst hack: verify data written
- if (dst::isFatDrive(targetObj) && !zen::dirExists(targetObj)) //throw()
+ if (dst::isFatDrive(targetObj) && !dirExists(targetObj)) //throw()
{
WIN32_FILE_ATTRIBUTE_DATA debugeAttr = {};
assert(::GetFileAttributesEx(applyLongPathPrefix(targetObj).c_str(), //__in LPCTSTR lpFileName,
@@ -918,7 +862,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
- throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + getLastErrorFormatted());
struct utimbuf newTimes = {};
newTimes.actime = objInfo.st_atime;
@@ -926,13 +870,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!
- throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + getLastErrorFormatted());
}
else
{
struct stat objInfo = {};
if (::lstat(sourceObj.c_str(), &objInfo) != 0) //read file attributes from source directory
- throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading file attributes:") + "\n\"" + sourceObj + "\"" + "\n\n" + getLastErrorFormatted());
struct timeval newTimes[2] = {};
newTimes[0].tv_sec = objInfo.st_atime; /* seconds */
@@ -942,7 +886,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!
- throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error changing modification time:") + "\n\"" + targetObj + "\"" + "\n\n" + getLastErrorFormatted());
}
#endif
}
@@ -954,7 +898,7 @@ namespace
Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target path of symbolic link to a directory; throw (FileError)
{
//open handle to target of symbolic link
- const HANDLE hDir = ::CreateFile(zen::applyLongPathPrefix(dirLinkName).c_str(),
+ const HANDLE hDir = ::CreateFile(applyLongPathPrefix(dirLinkName).c_str(),
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@@ -962,7 +906,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)
- throw FileError(_("Error resolving symbolic link:") + "\n\"" + dirLinkName + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error resolving symbolic link:") + "\n\"" + dirLinkName + "\"" + "\n\n" + getLastErrorFormatted());
Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hDir);
(void)dummy; //silence warning "unused variable"
@@ -976,7 +920,7 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
LPTSTR lpszFilePath,
DWORD cchFilePath,
DWORD dwFlags);
- static const GetFinalPathNameByHandleWFunc getFinalPathNameByHandle =
+ const GetFinalPathNameByHandleWFunc getFinalPathNameByHandle =
util::getDllFun<GetFinalPathNameByHandleWFunc>(L"kernel32.dll", "GetFinalPathNameByHandleW");
if (getFinalPathNameByHandle == NULL)
@@ -991,7 +935,7 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
{
std::wstring errorMessage = _("Error resolving symbolic link:") + "\n\"" + dirLinkName + "\"";
if (rv == 0)
- errorMessage += L"\n\n" + zen::getLastErrorFormatted();
+ errorMessage += L"\n\n" + getLastErrorFormatted();
throw FileError(errorMessage);
}
@@ -1014,7 +958,7 @@ void copySecurityContext(const Zstring& source, const Zstring& target, bool dere
errno == EOPNOTSUPP) //extended attributes are not supported by the filesystem
return;
- throw FileError(_("Error reading security context:") + "\n\"" + source + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error reading security context:") + "\n\"" + source + "\"" + "\n\n" + getLastErrorFormatted());
}
Loki::ScopeGuard dummy1 = Loki::MakeGuard(::freecon, contextSource);
(void)dummy1; //silence warning "unused variable"
@@ -1044,7 +988,7 @@ void copySecurityContext(const Zstring& source, const Zstring& target, bool dere
::setfilecon (target.c_str(), contextSource) :
::lsetfilecon(target.c_str(), contextSource);
if (rv3 < 0)
- throw FileError(_("Error writing security context:") + "\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error writing security context:") + "\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted());
}
#endif //HAVE_SELINUX
@@ -1077,7 +1021,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
PACL sacl = NULL;
//http://msdn.microsoft.com/en-us/library/aa364399(v=VS.85).aspx
- const HANDLE hSource = ::CreateFile(zen::applyLongPathPrefix(source).c_str(),
+ const HANDLE hSource = ::CreateFile(applyLongPathPrefix(source).c_str(),
READ_CONTROL | ACCESS_SYSTEM_SECURITY, //ACCESS_SYSTEM_SECURITY required for SACL access
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@@ -1085,7 +1029,7 @@ 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)
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (OR)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted() + " (OR)");
Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hSource);
(void)dummy; //silence warning "unused variable"
@@ -1100,7 +1044,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
&sacl, //__out_opt PACL *ppSacl,
&buffer); //__out_opt PSECURITY_DESCRIPTOR *ppSecurityDescriptor
if (rc != ERROR_SUCCESS)
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted(rc) + " (R)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted(rc) + " (R)");
Loki::ScopeGuard dummy4 = Loki::MakeGuard(::LocalFree, buffer);
(void)dummy4; //silence warning "unused variable"
@@ -1119,7 +1063,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
});
if (targetHandle.get() == INVALID_HANDLE_VALUE)
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (OW)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted() + " (OW)");
// rc = ::SetNamedSecurityInfo(const_cast<WCHAR*>(applyLongPathPrefix(target).c_str()), //__in LPTSTR pObjectName, -> does NOT dereference symlinks!
rc = ::SetSecurityInfo(
@@ -1132,7 +1076,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
sacl); //__in_opt PACL pSacl
if (rc != ERROR_SUCCESS)
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted(rc) + " (W)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted(rc) + " (W)");
#elif defined FFS_LINUX
@@ -1146,7 +1090,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
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)
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (R)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted() + " (R)");
}
else
{
@@ -1154,7 +1098,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
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()
- throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + zen::getLastErrorFormatted() + " (W)");
+ throw FileError(_("Error copying file permissions:") + "\n\"" + source + "\" ->\n\"" + target + "\"" + "\n\n" + getLastErrorFormatted() + " (W)");
}
#endif
}
@@ -1163,8 +1107,8 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, bool de
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 removeDirSimple(const Zstring& directory) { removeDirectory(directory); } //throw (FileError)
+void removeFileSimple(const Zstring& filename) { removeFile(filename); } //throw (FileError)
}
@@ -1172,7 +1116,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
{
using namespace zen;
- if (zen::dirExists(directory))
+ if (dirExists(directory))
return;
if (level == 100) //catch endless recursion
@@ -1180,7 +1124,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
//try to create parent folders first
const Zstring dirParent = directory.BeforeLast(FILE_NAME_SEPARATOR);
- if (!dirParent.empty() && !zen::dirExists(dirParent))
+ if (!dirParent.empty() && !dirExists(dirParent))
{
//call function recursively
const Zstring templateParent = templateDir.BeforeLast(FILE_NAME_SEPARATOR);
@@ -1201,7 +1145,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
#endif
{
if (level != 0) return;
- throw FileError(_("Error creating directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error creating directory:") + "\n\"" + directory + "\"" + "\n\n" + getLastErrorFormatted());
}
if (!templateDir.empty())
@@ -1314,7 +1258,7 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, zen:
#ifdef FFS_WIN
//dynamically load windows API function
typedef BOOLEAN (WINAPI *CreateSymbolicLinkFunc)(LPCTSTR lpSymlinkFileName, LPCTSTR lpTargetFileName, DWORD dwFlags);
- static const CreateSymbolicLinkFunc createSymbolicLink = util::getDllFun<CreateSymbolicLinkFunc>(L"kernel32.dll", "CreateSymbolicLinkW");
+ const CreateSymbolicLinkFunc createSymbolicLink = util::getDllFun<CreateSymbolicLinkFunc>(L"kernel32.dll", "CreateSymbolicLinkW");
if (createSymbolicLink == NULL)
throw FileError(_("Error loading library function:") + "\n\"" + "CreateSymbolicLinkW" + "\"");
@@ -1322,11 +1266,11 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, zen:
targetLink.c_str(), //__in LPTSTR lpSymlinkFileName,
linkPath.c_str(), //__in LPTSTR lpTargetFileName,
(type == SYMLINK_TYPE_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0))) //__in DWORD dwFlags
- throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + getLastErrorFormatted());
#elif defined FFS_LINUX
if (::symlink(linkPath.c_str(), targetLink.c_str()) != 0)
- throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + zen::getLastErrorFormatted());
+ throw FileError(_("Error copying symbolic link:") + "\n\"" + sourceLink + "\" ->\n\"" + targetLink + "\"" + "\n\n" + getLastErrorFormatted());
#endif
//allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist
@@ -1351,7 +1295,7 @@ Zstring createTempName(const Zstring& filename)
Zstring output = filename + zen::TEMP_FILE_ENDING;
//ensure uniqueness
- for (int i = 1; zen::somethingExists(output); ++i)
+ for (int i = 1; somethingExists(output); ++i)
output = filename + Zchar('_') + Zstring::fromNumber(i) + zen::TEMP_FILE_ENDING;
return output;
@@ -1362,11 +1306,13 @@ struct CallbackData
{
CallbackData(CallbackCopyFile& cb) :
callback(cb),
+ callNr(0),
exceptionCaught(false) {}
CallbackCopyFile& callback;
+ size_t callNr;
bool exceptionCaught;
- zen::UInt64 bytesTransferredOnException;
+ UInt64 bytesTransferredOnException;
};
@@ -1381,14 +1327,13 @@ DWORD CALLBACK copyCallbackInternal(
HANDLE hDestinationFile,
LPVOID lpData)
{
- //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)
{
- if (lpData)
- {
- CallbackData& cbd = *static_cast<CallbackData*>(lpData);
+ CallbackData& cbd = *static_cast<CallbackData*>(lpData);
+ //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size).
+ if (++cbd.callNr % 4 == 0) //executing callback every 256 kB should suffice
+ {
//some odd check for some possible(?) error condition
if (totalBytesTransferred.QuadPart < 0) //let's see if someone answers the call...
::MessageBox(NULL, L"You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\
@@ -1398,12 +1343,15 @@ DWORD CALLBACK copyCallbackInternal(
NULL, 0);
try
{
- cbd.callback.updateCopyStatus(zen::UInt64(totalBytesTransferred.QuadPart));
+ cbd.callback.updateCopyStatus(UInt64(totalBytesTransferred.QuadPart));
}
catch (...)
{
+#ifndef _MSC_VER
+#warning migrate to std::exception_ptr when available
+#endif
cbd.exceptionCaught = true;
- cbd.bytesTransferredOnException = zen::UInt64(totalBytesTransferred.QuadPart);
+ cbd.bytesTransferredOnException = UInt64(totalBytesTransferred.QuadPart);
return PROGRESS_CANCEL;
}
}
@@ -1413,23 +1361,6 @@ DWORD CALLBACK copyCallbackInternal(
}
-#ifndef COPY_FILE_COPY_SYMLINK
-#define COPY_FILE_COPY_SYMLINK 0x00000800
-#endif
-
-bool supportForSymbolicLinks()
-{
- OSVERSIONINFO osvi = {};
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-
- //symbolic links are supported starting with Vista
- if (::GetVersionEx(&osvi))
- return osvi.dwMajorVersion > 5; //XP has majorVersion == 5, minorVersion == 1; Vista majorVersion == 6, dwMinorVersion == 0
- //overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
- return false;
-}
-
-
#ifndef COPY_FILE_ALLOW_DECRYPTED_DESTINATION
#define COPY_FILE_ALLOW_DECRYPTED_DESTINATION 0x00000008
#endif
@@ -1456,12 +1387,12 @@ void rawCopyWinApi(const Zstring& sourceFile,
DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
- // static const bool symlinksSupported = supportForSymbolicLinks(); //only set "true" if supported by OS: else copying in Windows XP fails
- // if (copyFileSymLinks && symlinksSupported)
- // copyFlags |= COPY_FILE_COPY_SYMLINK;
-
//allow copying from encrypted to non-encrytped location
- static const bool nonEncSupported = supportForNonEncryptedDestination();
+
+ static bool nonEncSupported = false;
+ static boost::once_flag once = BOOST_ONCE_INIT; //caveat: function scope static initialization is not thread-safe in VS 2010!
+ boost::call_once(once, []() { nonEncSupported = supportForNonEncryptedDestination(); });
+
if (nonEncSupported)
copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION;
@@ -1484,7 +1415,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
//assemble error message...
std::wstring errorMessage = _("Error copying file:") + "\n\"" + sourceFile + "\" ->\n\"" + targetFile + "\"" +
- "\n\n" + zen::getLastErrorFormatted(lastError);
+ "\n\n" + getLastErrorFormatted(lastError);
//if file is locked (try to) use Windows Volume Shadow Copy Service
if (lastError == ERROR_SHARING_VIOLATION ||
@@ -1508,7 +1439,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
//trying to copy > 4GB file to FAT/FAT32 volume gives obscure ERROR_INVALID_PARAMETER (FAT can indeed handle files up to 4 Gig, tested!)
if (lastError == ERROR_INVALID_PARAMETER &&
dst::isFatDrive(targetFile) &&
- getFilesize(sourceFile) >= 4U * zen::UInt64(1024U * 1024 * 1024)) //throw (FileError)
+ getFilesize(sourceFile) >= 4U * UInt64(1024U * 1024 * 1024)) //throw (FileError)
errorMessage += L"\nFAT volume cannot store files larger than 4 gigabyte!";
}
catch(...) {}
@@ -1555,7 +1486,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// */
//
// //open sourceFile for reading
-// HANDLE hFileIn = ::CreateFile(zen::applyLongPathPrefix(sourceFile).c_str(),
+// HANDLE hFileIn = ::CreateFile(applyLongPathPrefix(sourceFile).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
// NULL,
@@ -1565,7 +1496,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// if (hFileIn == INVALID_HANDLE_VALUE)
// {
// const DWORD lastError = ::GetLastError();
-// const std::wstring& errorMessage = _("Error opening file:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted(lastError);
+// const std::wstring& errorMessage = _("Error opening file:") + "\n\"" + sourceFile + "\"" + "\n\n" + getLastErrorFormatted(lastError);
//
// //if file is locked (try to) use Windows Volume Shadow Copy Service
// if (lastError == ERROR_SHARING_VIOLATION ||
@@ -1580,7 +1511,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
//
// BY_HANDLE_FILE_INFORMATION infoFileIn = {};
// if (!::GetFileInformationByHandle(hFileIn, &infoFileIn))
-// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted());
+// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + getLastErrorFormatted());
//
// //####################################### DST hack ###########################################
// if (dst::isFatDrive(sourceFile)) //throw()
@@ -1609,7 +1540,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// FILE_ATTRIBUTE_ENCRYPTED;
//
// //create targetFile and open it for writing
-// HANDLE hFileOut = ::CreateFile(zen::applyLongPathPrefix(targetFile).c_str(),
+// HANDLE hFileOut = ::CreateFile(applyLongPathPrefix(targetFile).c_str(),
// GENERIC_READ | GENERIC_WRITE, //read access required for FSCTL_SET_COMPRESSION
// FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
// NULL,
@@ -1620,7 +1551,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// {
// const DWORD lastError = ::GetLastError();
// const std::wstring& errorMessage = _("Error writing file:") + "\n\"" + targetFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted(lastError);
+// "\n\n" + getLastErrorFormatted(lastError);
//
// if (lastError == ERROR_FILE_EXISTS)
// throw ErrorTargetExisting(errorMessage);
@@ -1648,7 +1579,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// &fsFlags, //__out_opt LPDWORD lpFileSystemFlags,
// NULL, //__out LPTSTR lpFileSystemNameBuffer,
// 0)) //__in DWORD nFileSystemNameSize
-// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted());
+// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + getLastErrorFormatted());
//
// const bool sourceIsEncrypted = (infoFileIn.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0;
// const bool sourceIsCompressed = (infoFileIn.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0;
@@ -1675,7 +1606,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// &bytesReturned, //number of bytes returned
// NULL)) //OVERLAPPED structure
// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted() +
+// "\n\n" + getLastErrorFormatted() +
// "\nFailed to write NTFS compressed attribute!");
// }
//
@@ -1694,14 +1625,17 @@ void rawCopyWinApi(const Zstring& sourceFile,
// &bytesReturned, //number of bytes returned
// NULL)) //OVERLAPPED structure
// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted() +
+// "\n\n" + getLastErrorFormatted() +
// "\nFailed to write NTFS sparse attribute!");
// }
// }
//
//
// const DWORD BUFFER_SIZE = 512 * 1024; //512 kb seems to be a reasonable buffer size
-// static const boost::scoped_array<BYTE> memory(new BYTE[BUFFER_SIZE]);
+// static boost::thread_specific_ptr<std::vector<char>> cpyBuf;
+// if (!cpyBuf.get())
+// cpyBuf.reset(new std::vector<char>(BUFFER_SIZE)); //512 kb seems to be a reasonable buffer size
+// std::vector<char>& buffer = *cpyBuf;
//
// struct ManageCtxt //manage context for BackupRead()/BackupWrite()
// {
@@ -1719,7 +1653,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// } context;
//
// //copy contents of sourceFile to targetFile
-// zen::UInt64 totalBytesTransferred;
+// UInt64 totalBytesTransferred;
//
// bool eof = false;
// do
@@ -1729,22 +1663,22 @@ void rawCopyWinApi(const Zstring& sourceFile,
// if (useBackupFun)
// {
// if (!::BackupRead(hFileIn, //__in HANDLE hFile,
-// memory.get(), //__out LPBYTE lpBuffer,
+// &buffer[0], //__out LPBYTE lpBuffer,
// BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead,
// &bytesRead, //__out LPDWORD lpNumberOfBytesRead,
// false, //__in BOOL bAbort,
// false, //__in BOOL bProcessSecurity,
// &context.read)) //__out LPVOID *lpContext
// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted());
+// "\n\n" + getLastErrorFormatted());
// }
// else if (!::ReadFile(hFileIn, //__in HANDLE hFile,
-// memory.get(), //__out LPVOID lpBuffer,
+// &buffer[0], //__out LPVOID lpBuffer,
// BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead,
// &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead,
// NULL)) //__inout_opt LPOVERLAPPED lpOverlapped
// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted());
+// "\n\n" + getLastErrorFormatted());
//
// if (bytesRead > BUFFER_SIZE)
// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" +
@@ -1758,22 +1692,22 @@ void rawCopyWinApi(const Zstring& sourceFile,
// if (useBackupFun)
// {
// if (!::BackupWrite(hFileOut, //__in HANDLE hFile,
-// memory.get(), //__in LPBYTE lpBuffer,
+// &buffer[0], //__in LPBYTE lpBuffer,
// bytesRead, //__in DWORD nNumberOfBytesToWrite,
// &bytesWritten, //__out LPDWORD lpNumberOfBytesWritten,
// false, //__in BOOL bAbort,
// false, //__in BOOL bProcessSecurity,
// &context.write)) //__out LPVOID *lpContext
// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message!
+// "\n\n" + getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message!
// }
// else if (!::WriteFile(hFileOut, //__in HANDLE hFile,
-// memory.get(), //__out LPVOID lpBuffer,
+// &buffer[0], //__out LPVOID lpBuffer,
// bytesRead, //__in DWORD nNumberOfBytesToWrite,
// &bytesWritten, //__out_opt LPDWORD lpNumberOfBytesWritten,
// NULL)) //__inout_opt LPOVERLAPPED lpOverlapped
// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" +
-// "\n\n" + zen::getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message!
+// "\n\n" + getLastErrorFormatted() + " (w)"); //w -> distinguish from fopen error message!
//
// if (bytesWritten != bytesRead)
// throw FileError(_("Error writing file:") + "\n\"" + targetFile + "\"" + "\n\n" + "incomplete write");
@@ -1803,7 +1737,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// {
// LARGE_INTEGER inputSize = {};
// if (!::GetFileSizeEx(hFileIn, &inputSize))
-// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + zen::getLastErrorFormatted());
+// throw FileError(_("Error reading file attributes:") + "\n\"" + sourceFile + "\"" + "\n\n" + getLastErrorFormatted());
//
// if (inputSize.QuadPart != 0)
// throw FileError(_("Error reading file:") + "\n\"" + sourceFile + "\"" + "\n\n" + "unknown error");
@@ -1814,7 +1748,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
// &infoFileIn.ftCreationTime,
// NULL,
// &infoFileIn.ftLastWriteTime))
-// throw FileError(_("Error changing modification time:") + "\n\"" + targetFile + "\"" + "\n\n" + zen::getLastErrorFormatted());
+// throw FileError(_("Error changing modification time:") + "\n\"" + targetFile + "\"" + "\n\n" + getLastErrorFormatted());
//
//
//#ifndef NDEBUG //dst hack: verify data written
@@ -1878,10 +1812,13 @@ void rawCopyStream(const Zstring& sourceFile,
//create targetFile and open it for writing
FileOutput fileOut(targetFile, FileOutput::ACC_CREATE_NEW); //throw (FileError: ErrorTargetPathMissing, ErrorTargetExisting)
- static std::vector<wchar_t> buffer(512 * 1024); //512 kb seems to be a reasonable buffer size
+ static boost::thread_specific_ptr<std::vector<char>> cpyBuf;
+ if (!cpyBuf.get())
+ cpyBuf.reset(new std::vector<char>(512 * 1024)); //512 kb seems to be a reasonable buffer size
+ std::vector<char>& buffer = *cpyBuf;
//copy contents of sourceFile to targetFile
- zen::UInt64 totalBytesTransferred;
+ UInt64 totalBytesTransferred;
do
{
const size_t bytesRead = fileIn.read(&buffer[0], buffer.size()); //throw (FileError)
@@ -1944,7 +1881,7 @@ void zen::copyFile(const Zstring& sourceFile, //throw (FileError: ErrorTargetPat
CallbackCopyFile* callback)
{
Zstring temporary = targetFile + zen::TEMP_FILE_ENDING; //use temporary file until a correct date has been set
- Loki::ScopeGuard guardTempFile = Loki::MakeGuard(&removeFile, boost::cref(temporary)); //transactional behavior: ensure cleanup (e.g. network drop) -> cref [!]
+ Loki::ScopeGuard guardTempFile = Loki::MakeGuard([&]() { removeFile(temporary); }); //transactional behavior: ensure cleanup (e.g. network drop) -> ref to temporary[!]
//raw file copy
try
diff --git a/shared/file_handling.h b/shared/file_handling.h
index 0ee4b1e9..113168f3 100644
--- a/shared/file_handling.h
+++ b/shared/file_handling.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILE_HANDLING_H_INCLUDED
#define FILE_HANDLING_H_INCLUDED
@@ -25,13 +25,15 @@ bool somethingExists(const Zstring& objname); //throw() check whether any
//check whether two folders are located on the same (logical) volume
//left and right directories NEED NOT yet exist! volume prefix is sufficient! path may end with PATH_SEPARATOR
-enum ResponseSameVol
+enum ResponseSame
{
- VOLUME_SAME,
- VOLUME_DIFFERENT,
- VOLUME_CANT_SAY
+ IS_SAME_YES,
+ IS_SAME_NO,
+ IS_SAME_CANT_SAY
};
-ResponseSameVol onSameVolume(const Zstring& folderLeft, const Zstring& folderRight); //throw()
+ResponseSame onSameVolume(const Zstring& folderLeft, const Zstring& folderRight); //throw()
+
+void checkthis(const Zstring& folderLeft); //throw()
//copy file or directory create/last change date,
void copyFileTimes(const Zstring& sourceDir, const Zstring& targetDir, bool derefSymlinks); //throw (FileError)
diff --git a/shared/file_id.cpp b/shared/file_id.cpp
index da8fd815..e6c016e7 100644
--- a/shared/file_id.cpp
+++ b/shared/file_id.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_id.h"
#ifdef FFS_WIN
@@ -18,8 +18,7 @@
namespace
{
-template <class T>
-inline
+template <class T> inline
std::string numberToBytes(T number)
{
const char* rawBegin = reinterpret_cast<const char*>(&number);
diff --git a/shared/file_id.h b/shared/file_id.h
index 2e94bf5a..eaf47e3c 100644
--- a/shared/file_id.h
+++ b/shared/file_id.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILEID_H_INCLUDED
#define FILEID_H_INCLUDED
diff --git a/shared/file_io.cpp b/shared/file_io.cpp
index c19101aa..2614ac06 100644
--- a/shared/file_io.cpp
+++ b/shared/file_io.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_io.h"
#include "last_error.h"
#include "i18n.h"
diff --git a/shared/file_io.h b/shared/file_io.h
index 79b521f1..6f87845b 100644
--- a/shared/file_io.h
+++ b/shared/file_io.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILEIO_H_INCLUDED
#define FILEIO_H_INCLUDED
diff --git a/shared/file_traverser.cpp b/shared/file_traverser.cpp
index aced3487..595b2768 100644
--- a/shared/file_traverser.cpp
+++ b/shared/file_traverser.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "file_traverser.h"
#include <limits>
#include "last_error.h"
@@ -14,6 +14,7 @@
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "long_path_prefix.h"
#include "dst_hack.h"
+#include "file_update_handle.h"
#elif defined FFS_LINUX
#include <sys/stat.h>
@@ -57,7 +58,7 @@ inline
zen::Int64 filetimeToTimeT(const FILETIME& lastWriteTime)
{
//convert UTC FILETIME to ANSI C format (number of seconds since Jan. 1st 1970 UTC)
- zen::Int64 writeTimeLong = zen::to<zen::Int64>(zen::UInt64(lastWriteTime.dwLowDateTime, lastWriteTime.dwHighDateTime) / 10000000U); //reduce precision to 1 second (FILETIME has unit 10^-7 s)
+ zen::Int64 writeTimeLong = to<zen::Int64>(zen::UInt64(lastWriteTime.dwLowDateTime, lastWriteTime.dwHighDateTime) / 10000000U); //reduce precision to 1 second (FILETIME has unit 10^-7 s)
writeTimeLong -= zen::Int64(3054539008UL, 2); //timeshift between ansi C time and FILETIME in seconds == 11644473600s
return writeTimeLong;
}
@@ -126,14 +127,12 @@ public:
}
private:
- DirTraverser(const DirTraverser&);
- DirTraverser& operator=(const DirTraverser&);
+ DirTraverser(const DirTraverser&);
+ DirTraverser& operator=(const DirTraverser&);
template <bool followSymlinks>
void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level)
{
- using namespace zen;
-
tryReportingError([&](std::wstring& errorMsg) -> bool
{
if (level == 100) //notify endless recursion
@@ -146,19 +145,16 @@ private:
#ifdef FFS_WIN
- //ensure directoryFormatted ends with backslash
- const Zstring& directoryFormatted = directory.EndsWith(FILE_NAME_SEPARATOR) ?
- directory :
- directory + FILE_NAME_SEPARATOR;
-
+ //ensure directoryPf ends with backslash
+ const Zstring& directoryPf = directory.EndsWith(FILE_NAME_SEPARATOR) ?
+ directory :
+ directory + FILE_NAME_SEPARATOR;
WIN32_FIND_DATA fileInfo = {};
HANDLE searchHandle = INVALID_HANDLE_VALUE;
tryReportingError([&](std::wstring& errorMsg) -> bool
{
- searchHandle = ::FindFirstFile(
- applyLongPathPrefix(directoryFormatted + Zchar('*')).c_str(), //__in LPCTSTR lpFileName
- &fileInfo); //__out LPWIN32_FIND_DATA lpFindFileData
+ searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo);
//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)
@@ -188,7 +184,7 @@ private:
(shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0')))
continue;
- const Zstring& fullName = directoryFormatted + shortName;
+ const Zstring& fullName = directoryPf + shortName;
const bool isSymbolicLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
@@ -254,7 +250,7 @@ private:
details.fileSize = zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
}
- sink.onFile(shortName, fullName, details);
+ sink.onFile(shortName, fullName, details);
}
}
while ([&]() -> bool
@@ -322,7 +318,7 @@ private:
//don't return "." and ".."
- const Zchar* const shortName = dirEntry->d_name;
+ const char* const shortName = dirEntry->d_name;
if (shortName[0] == '.' &&
(shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0')))
continue;
@@ -421,23 +417,25 @@ private:
const dst::RawTime encodedTime = dst::fatEncodeUtcTime(i->second); //throw (std::runtime_error)
{
- HANDLE hTarget = ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(),
- 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,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
- if (hTarget == INVALID_HANDLE_VALUE)
+ //may need to remove the readonly-attribute (e.g. FAT usb drives)
+ FileUpdateHandle updateHandle(i->first, [=]()
+ {
+ return ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(),
+ 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,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ });
+ if (updateHandle.get() == INVALID_HANDLE_VALUE)
{
++failedAttempts;
assert(false); //don't throw exceptions due to dst hack here
continue;
}
- Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, hTarget);
- (void)dummy; //silence warning "unused variable"
- if (!::SetFileTime(hTarget,
+ if (!::SetFileTime(updateHandle.get(),
&encodedTime.createTimeRaw,
NULL,
&encodedTime.writeTimeRaw))
@@ -483,7 +481,7 @@ void zen::traverseFolder(const Zstring& directory, bool followSymlinks, Traverse
#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)
+ zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError
}
catch (...) {} //don't cause issues in user mode
#endif
diff --git a/shared/file_traverser.h b/shared/file_traverser.h
index 18d692df..aa9dffad 100644
--- a/shared/file_traverser.h
+++ b/shared/file_traverser.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FILETRAVERSER_H_INCLUDED
#define FILETRAVERSER_H_INCLUDED
diff --git a/shared/file_update_handle.h b/shared/file_update_handle.h
new file mode 100644
index 00000000..1ffb7000
--- /dev/null
+++ b/shared/file_update_handle.h
@@ -0,0 +1,67 @@
+#ifndef FILE_UPDATE_HANDLE_H_INCLUDED
+#define FILE_UPDATE_HANDLE_H_INCLUDED
+
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "long_path_prefix.h"
+
+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(zen::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;
+};
+}
+
+#endif // FILE_UPDATE_HANDLE_H_INCLUDED
diff --git a/shared/global_func.h b/shared/global_func.h
index bf9f13dd..861e2081 100644
--- a/shared/global_func.h
+++ b/shared/global_func.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef GLOBALFUNCTIONS_H_INCLUDED
#define GLOBALFUNCTIONS_H_INCLUDED
diff --git a/shared/guid.cpp b/shared/guid.cpp
index 1580a62d..1cc304cb 100644
--- a/shared/guid.cpp
+++ b/shared/guid.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "guid.h"
#include <boost/uuid/uuid.hpp>
diff --git a/shared/guid.h b/shared/guid.h
index 166e9eb1..1986b101 100644
--- a/shared/guid.h
+++ b/shared/guid.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef GUID_H_INCLUDED
#define GUID_H_INCLUDED
diff --git a/shared/help_provider.cpp b/shared/help_provider.cpp
index 2c5d5aa9..7eb043cd 100644
--- a/shared/help_provider.cpp
+++ b/shared/help_provider.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "help_provider.h"
#include <wx/help.h>
#include "standard_paths.h"
diff --git a/shared/help_provider.h b/shared/help_provider.h
index 01ac3054..dbe3ce26 100644
--- a/shared/help_provider.h
+++ b/shared/help_provider.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef HELPPROVIDER_H_INCLUDED
#define HELPPROVIDER_H_INCLUDED
diff --git a/shared/i18n.h b/shared/i18n.h
index cac6555c..8aa38f3c 100644
--- a/shared/i18n.h
+++ b/shared/i18n.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef I18_N_HEADER_3843489325045
#define I18_N_HEADER_3843489325045
diff --git a/shared/int64.h b/shared/int64.h
index 15900fde..61ef1716 100644
--- a/shared/int64.h
+++ b/shared/int64.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FFS_LARGE_64_BIT_INTEGER_H_INCLUDED
#define FFS_LARGE_64_BIT_INTEGER_H_INCLUDED
diff --git a/shared/last_error.cpp b/shared/last_error.cpp
index ea8345bc..57053c30 100644
--- a/shared/last_error.cpp
+++ b/shared/last_error.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "last_error.h"
#include "string_utf8.h"
#include "i18n.h"
diff --git a/shared/last_error.h b/shared/last_error.h
index b617ebf5..3e90a1a0 100644
--- a/shared/last_error.h
+++ b/shared/last_error.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SYSTEMFUNCTIONS_H_INCLUDED
#define SYSTEMFUNCTIONS_H_INCLUDED
diff --git a/shared/localization.cpp b/shared/localization.cpp
index 919009d6..66b2d97b 100644
--- a/shared/localization.cpp
+++ b/shared/localization.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "localization.h"
#include <fstream>
#include <map>
diff --git a/shared/localization.h b/shared/localization.h
index 07ac2a69..438ad445 100644
--- a/shared/localization.h
+++ b/shared/localization.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef MISC_H_INCLUDED
#define MISC_H_INCLUDED
diff --git a/shared/long_path_prefix.h b/shared/long_path_prefix.h
index b6da9168..45fde0fa 100644
--- a/shared/long_path_prefix.h
+++ b/shared/long_path_prefix.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef LONGPATHPREFIX_H_INCLUDED
#define LONGPATHPREFIX_H_INCLUDED
diff --git a/shared/mouse_move_dlg.cpp b/shared/mouse_move_dlg.cpp
index 95074b55..7981df49 100644
--- a/shared/mouse_move_dlg.cpp
+++ b/shared/mouse_move_dlg.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "mouse_move_dlg.h"
#include <vector>
#include <wx/msw/wrapwin.h> //includes "windows.h"
diff --git a/shared/mouse_move_dlg.h b/shared/mouse_move_dlg.h
index 2e23c089..4412529c 100644
--- a/shared/mouse_move_dlg.h
+++ b/shared/mouse_move_dlg.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef MOUSEMOVEWINDOW_H_INCLUDED
#define MOUSEMOVEWINDOW_H_INCLUDED
diff --git a/shared/notify_removal.cpp b/shared/notify_removal.cpp
index 819604ad..3a9239db 100644
--- a/shared/notify_removal.cpp
+++ b/shared/notify_removal.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "notify_removal.h"
#include <set>
#include "last_error.h"
@@ -183,8 +183,8 @@ public:
}
private:
- Pimpl(Pimpl&);
- Pimpl& operator=(Pimpl&);
+ Pimpl(Pimpl&);
+ Pimpl& operator=(Pimpl&);
virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) //throw()!
{
diff --git a/shared/notify_removal.h b/shared/notify_removal.h
index abdf460b..f9d1cbaf 100644
--- a/shared/notify_removal.h
+++ b/shared/notify_removal.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef NOTIFY_H_INCLUDED
#define NOTIFY_H_INCLUDED
diff --git a/shared/parse_lng.h b/shared/parse_lng.h
index fcf20d28..b943d222 100644
--- a/shared/parse_lng.h
+++ b/shared/parse_lng.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef PARSE_LNG_HEADER_INCLUDED
#define PARSE_LNG_HEADER_INCLUDED
diff --git a/shared/parse_plural.h b/shared/parse_plural.h
index 3837feba..1139ffb6 100644
--- a/shared/parse_plural.h
+++ b/shared/parse_plural.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef PARSE_PLURAL_H_INCLUDED
#define PARSE_PLURAL_H_INCLUDED
diff --git a/shared/parse_txt.h b/shared/parse_txt.h
index 56147425..ca155dec 100644
--- a/shared/parse_txt.h
+++ b/shared/parse_txt.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef PARSE_TXT_H_INCLUDED
#define PARSE_TXT_H_INCLUDED
diff --git a/shared/pch.h b/shared/pch.h
index 06d6b417..aae74c08 100644
--- a/shared/pch.h
+++ b/shared/pch.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef FFS_PRECOMPILED_HEADER
#define FFS_PRECOMPILED_HEADER
diff --git a/shared/perf.h b/shared/perf.h
index f62f9cc0..9bcf7882 100644
--- a/shared/perf.h
+++ b/shared/perf.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef DEBUG_PERF_HEADER
#define DEBUG_PERF_HEADER
diff --git a/shared/recycler.cpp b/shared/recycler.cpp
index cc216d4f..92b7b222 100644
--- a/shared/recycler.cpp
+++ b/shared/recycler.cpp
@@ -3,13 +3,15 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "recycler.h"
#include <stdexcept>
#include <iterator>
#include "i18n.h"
+#include "file_handling.h"
#ifdef FFS_WIN
+#include <boost/thread/once.hpp>
#include "dll_loader.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "build_info.h"
@@ -45,7 +47,6 @@ std::wstring getRecyclerDllName()
bool vistaOrLater()
{
OSVERSIONINFO osvi = {};
- ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
//IFileOperation is supported with Vista and later
@@ -72,12 +73,12 @@ Nevertheless, let's use IFileOperation for better error reporting!
void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (FileError)
{
- using zen::FileError;
-
if (filesToDelete.empty())
return;
- static const bool useIFileOperation = vistaOrLater();
+ static bool useIFileOperation = false;
+ static boost::once_flag once = BOOST_ONCE_INIT; //caveat: function scope static initialization is not thread-safe in VS 2010!
+ boost::call_once(once, []() { useIFileOperation = vistaOrLater(); });
if (useIFileOperation) //new recycle bin usage: available since Vista
{
@@ -86,14 +87,8 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (
std::back_inserter(fileNames), std::mem_fun_ref(&Zstring::c_str));
using namespace fileop;
-
- static MoveToRecycleBinFct moveToRecycler = NULL;
- if (!moveToRecycler)
- moveToRecycler = util::getDllFun<MoveToRecycleBinFct>(getRecyclerDllName(), moveToRecycleBinFctName);
-
- static GetLastErrorFct getLastError = NULL;
- if (!getLastError)
- getLastError = util::getDllFun<GetLastErrorFct>(getRecyclerDllName(), getLastErrorFctName);
+ MoveToRecycleBinFct moveToRecycler = util::getDllFun<MoveToRecycleBinFct>(getRecyclerDllName(), moveToRecycleBinFctName);
+ GetLastErrorFct getLastError = util::getDllFun<GetLastErrorFct> (getRecyclerDllName(), getLastErrorFctName);
if (moveToRecycler == NULL || getLastError == NULL)
throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileNames[0] + "\"" + //report first file only... better than nothing
@@ -122,7 +117,7 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (
//filenameDoubleNull += removeLongPathPrefix(*i); //::SHFileOperation() can't handle \\?\-prefix!
//You should use fully-qualified path names with this function. Using it with relative path names is not thread safe.
filenameDoubleNull += *i; //::SHFileOperation() can't handle \\?\-prefix!
- filenameDoubleNull += Zchar(0);
+ filenameDoubleNull += L'\0';
}
SHFILEOPSTRUCT fileOp = {};
@@ -137,7 +132,7 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (
if (::SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted)
{
- throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filenameDoubleNull.c_str() + "\""); //report first file only... better than nothing
+ throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filenameDoubleNull + "\""); //report first file only... better than nothing
}
}
}
@@ -145,41 +140,48 @@ void moveToWindowsRecycler(const std::vector<Zstring>& filesToDelete) //throw (
}
-bool zen::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileError)
+bool zen::moveToRecycleBin(const Zstring& filename) //throw (FileError)
{
-#ifdef FFS_WIN
- const Zstring filenameFmt = applyLongPathPrefix(fileToDelete);
-
- const DWORD attr = ::GetFileAttributes(filenameFmt.c_str());
- if (attr == INVALID_FILE_ATTRIBUTES)
+ if (!somethingExists(filename))
return false; //neither file nor any other object with that name existing: no error situation, manual deletion relies on it!
- //::SetFileAttributes(filenameFmt.c_str(), FILE_ATTRIBUTE_NORMAL);
- //both SHFileOperation and useIFileOperation are not able to delete a folder named "System Volume Information" with normal attributes but shamelessly report success
+#ifdef FFS_WIN
+ //::SetFileAttributes(applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_NORMAL);
+ //both SHFileOperation and IFileOperation are not able to delete a folder named "System Volume Information" with normal attributes but shamelessly report success
std::vector<Zstring> fileNames;
- fileNames.push_back(fileToDelete);
+ fileNames.push_back(filename);
::moveToWindowsRecycler(fileNames); //throw (FileError)
#elif defined FFS_LINUX
- struct stat fileInfo = {};
- 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
+ Glib::RefPtr<Gio::File> fileObj = Gio::File::create_for_path(filename.c_str()); //never fails
try
{
if (!fileObj->trash())
- throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileToDelete + "\"" +
+ throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filename + "\"" +
"\n\n" + "(unknown error)");
}
catch (const Glib::Error& errorObj)
{
+ //implement same behavior as in Windows: if recycler is not existing, delete permanently
+ if (errorObj.code() == G_IO_ERROR_NOT_SUPPORTED)
+ {
+ struct stat fileInfo = {};
+ if (::lstat(filename.c_str(), &fileInfo) != 0)
+ return false;
+
+ if (S_ISLNK(fileInfo.st_mode) || S_ISREG(fileInfo.st_mode))
+ removeFile(filename); //throw FileError
+ else if (S_ISDIR(fileInfo.st_mode))
+ removeDirectory(filename); //throw FileError
+ return true;
+ }
+
//assemble error message
- const std::wstring errorMessage = L"Glib Error Code " + toString<std::wstring>(errorObj.code()) + ", " +
- g_quark_to_string(errorObj.domain()) + ": " + errorObj.what();
+ const std::wstring errorMessage = L"Glib Error Code " + toString<std::wstring>(errorObj.code()) + /* ", " +
+ g_quark_to_string(errorObj.domain()) + */ ": " + errorObj.what();
- throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + fileToDelete + "\"" +
+ throw FileError(_("Error moving to Recycle Bin:") + "\n\"" + filename + "\"" +
"\n\n" + "(" + errorMessage + ")");
}
#endif
@@ -188,15 +190,15 @@ bool zen::moveToRecycleBin(const Zstring& fileToDelete) //throw (FileError)
#ifdef FFS_WIN
-zen::StatusRecycler zen::recycleBinExists(const Zstring& pathName)
+zen::StatusRecycler zen::recycleBinStatus(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
+ Zstring rootPath = &buffer[0];
+ if (!endsWith(rootPath, FILE_NAME_SEPARATOR)) //a trailing backslash is required
rootPath += FILE_NAME_SEPARATOR;
SHQUERYRBINFO recInfo = {};
@@ -207,4 +209,22 @@ zen::StatusRecycler zen::recycleBinExists(const Zstring& pathName)
}
return STATUS_REC_UNKNOWN;
}
+#elif defined FFS_LINUX
+/*
+We really need access to a similar function to check whether a directory supports trashing and emit a warning if it does not!
+
+The following function looks perfect, alas it is restricted to local files and to the implementation of GIO only:
+
+ gboolean _g_local_file_has_trash_dir(const char* dirname, dev_t dir_dev);
+ See: http://www.netmite.com/android/mydroid/2.0/external/bluetooth/glib/gio/glocalfileinfo.h
+
+ Just checking for "G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH" is not correct, since we find in
+ http://www.netmite.com/android/mydroid/2.0/external/bluetooth/glib/gio/glocalfileinfo.c
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+ writable && parent_info->has_trash_dir);
+
+ => We're NOT interested in whether the specified folder can be trashed, but whether it supports thrashing its child elements! (Only support, not actual write access!)
+ This renders G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH useless for this purpose.
+*/
#endif
diff --git a/shared/recycler.h b/shared/recycler.h
index da6e3123..718b64cc 100644
--- a/shared/recycler.h
+++ b/shared/recycler.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef RECYCLER_H_INCLUDED
#define RECYCLER_H_INCLUDED
@@ -23,15 +23,12 @@ Recycler always available: during runtime either SHFileOperation or (since Vista
Linux
-----
-Include compilation flag:
-`pkg-config --cflags gtkmm-2.4`
-
-Linker flag:
-`pkg-config --libs gtkmm-2.4`
+Compiler flag: `pkg-config --cflags gtkmm-2.4`
+Linker flag: `pkg-config --libs gtkmm-2.4`
*/
-//move a file or folder to Recycle Bin
-bool moveToRecycleBin(const Zstring& fileToDelete); //return "true" if file/dir was actually deleted; throw (FileError)
+//move a file or folder to Recycle Bin (deletes permanently if recycle is not available)
+bool moveToRecycleBin(const Zstring& filename); //return "true" if file/dir was actually deleted; throw (FileError)
#ifdef FFS_WIN
@@ -42,7 +39,7 @@ enum StatusRecycler
STATUS_REC_UNKNOWN
};
-StatusRecycler recycleBinExists(const Zstring& pathName); //test existence of Recycle Bin API for certain path
+StatusRecycler recycleBinStatus(const Zstring& pathName); //test existence of Recycle Bin API for certain path
#endif
}
diff --git a/shared/resolve_path.cpp b/shared/resolve_path.cpp
index 19dc0011..a9d1e0e5 100644
--- a/shared/resolve_path.cpp
+++ b/shared/resolve_path.cpp
@@ -8,6 +8,9 @@
#include "dll_loader.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "long_path_prefix.h"
+#ifdef _MSC_VER
+#pragma comment(lib, "Mpr.lib")
+#endif
#elif defined FFS_LINUX
#include <map>
@@ -21,20 +24,42 @@ using namespace zen;
namespace
{
#ifdef FFS_WIN
-Zstring resolveRelativePath(const Zstring& relativeName, DWORD proposedBufferSize = 1000)
+Zstring resolveBrokenNetworkMap(const Zstring& dirname) //circumvent issue with disconnected network maps that could be activated by a simple explorer double click
{
- std::vector<Zchar> fullPath(proposedBufferSize);
-
- const DWORD rv = ::GetFullPathName(
- applyLongPathPrefix(relativeName).c_str(), //__in LPCTSTR lpFileName,
- proposedBufferSize, //__in DWORD nBufferLength,
- &fullPath[0], //__out LPTSTR lpBuffer,
- NULL); //__out LPTSTR *lpFilePart
- if (rv == 0 || rv == proposedBufferSize)
+ if (dirname.size() >= 2 && iswalpha(dirname[0]) && dirname[1] == L':')
+ {
+ Zstring driveLetter(dirname.c_str(), 2); //e.g.: "Q:"
+ if (::GetFileAttributes((driveLetter + L'\\').c_str()) == INVALID_FILE_ATTRIBUTES)
+ {
+ DWORD bufferSize = 10000;
+ std::vector<wchar_t> remoteNameBuffer(bufferSize);
+ DWORD rv = ::WNetGetConnection(driveLetter.c_str(), //__in LPCTSTR lpLocalName in the form "<driveletter>:"
+ &remoteNameBuffer[0], //__out LPTSTR lpRemoteName,
+ &bufferSize); //__inout LPDWORD lpnLength
+ (void)rv;
+ //no error check here! remoteNameBuffer will be filled on ERROR_CONNECTION_UNAVAIL and maybe others?
+ Zstring networkShare = &remoteNameBuffer[0];
+ if (!networkShare.empty())
+ return networkShare + (dirname.c_str() + 2); //replace "Q:\subdir" by "\\server\share\subdir"
+ }
+ }
+ return dirname;
+}
+
+
+Zstring resolveRelativePath(Zstring relativeName)
+{
+ relativeName = resolveBrokenNetworkMap(relativeName);
+
+ std::vector<Zchar> fullPath(10000);
+
+ const DWORD rv = ::GetFullPathName(applyLongPathPrefix(relativeName).c_str(), //__in LPCTSTR lpFileName,
+ static_cast<DWORD>(fullPath.size()), //__in DWORD nBufferLength,
+ &fullPath[0], //__out LPTSTR lpBuffer,
+ NULL); //__out LPTSTR *lpFilePart
+ if (rv == 0 || rv >= fullPath.size()) //theoretically, rv can never be == fullPath.size()
//ERROR! Don't do anything
return relativeName;
- if (rv > proposedBufferSize)
- return resolveRelativePath(relativeName, rv);
return &fullPath[0];
}
diff --git a/shared/resolve_path.h b/shared/resolve_path.h
index 4ee1a90f..f6ae58cb 100644
--- a/shared/resolve_path.h
+++ b/shared/resolve_path.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef RESOLVE_PATH_H_INCLUDED
#define RESOLVE_PATH_H_INCLUDED
diff --git a/shared/serialize.cpp b/shared/serialize.cpp
index c2da1202..26102820 100644
--- a/shared/serialize.cpp
+++ b/shared/serialize.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "serialize.h"
#include "i18n.h"
diff --git a/shared/serialize.h b/shared/serialize.h
index 769b8671..c8a94ad1 100644
--- a/shared/serialize.h
+++ b/shared/serialize.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SERIALIZE_H_INCLUDED
#define SERIALIZE_H_INCLUDED
diff --git a/shared/shadow.cpp b/shared/shadow.cpp
index 948050b6..f000a69b 100644
--- a/shared/shadow.cpp
+++ b/shared/shadow.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "shadow.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "i18n.h"
@@ -14,8 +14,8 @@
#include "ShadowCopy\shadow.h"
#include "Loki/ScopeGuard.h"
-using shadow::ShadowCopy;
using namespace zen;
+using namespace shadow;
namespace
@@ -23,7 +23,6 @@ namespace
bool newerThanXP()
{
OSVERSIONINFO osvi = {};
- ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (::GetVersionEx(&osvi))
@@ -43,7 +42,7 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m
HANDLE hProcess,
PBOOL Wow64Process);
- static const IsWow64ProcessFun isWow64Process =
+ const IsWow64ProcessFun isWow64Process =
util::getDllFun<IsWow64ProcessFun>(L"kernel32.dll", "IsWow64Process");
if (isWow64Process)
@@ -87,13 +86,8 @@ public:
ShadowVolume(const Zstring& volumeNameFormatted) : //throw(FileError)
backupHandle(0)
{
- using namespace shadow;
-
- if (!createShadowCopy)
- createShadowCopy = util::getDllFun<CreateShadowCopyFct>(getShadowDllName(), createShadowCopyFctName);
-
- if (!releaseShadowCopy)
- releaseShadowCopy = util::getDllFun<ReleaseShadowCopyFct>(getShadowDllName(), releaseShadowCopyFctName);
+ createShadowCopy = util::getDllFun<CreateShadowCopyFct>(getShadowDllName(), createShadowCopyFctName);
+ releaseShadowCopy = util::getDllFun<ReleaseShadowCopyFct>(getShadowDllName(), releaseShadowCopyFctName);
//check if shadow copy dll was loaded correctly
if (createShadowCopy == NULL ||
@@ -103,8 +97,7 @@ public:
//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)
+ if (runningWOW64())
throw FileError(_("Error starting Volume Shadow Copy Service!") + "\n" +
_("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version."));
@@ -140,24 +133,18 @@ private:
ShadowVolume(const ShadowVolume&);
ShadowVolume& operator=(const ShadowVolume&);
- static shadow::CreateShadowCopyFct createShadowCopy;
- static shadow::ReleaseShadowCopyFct releaseShadowCopy;
+ shadow::CreateShadowCopyFct createShadowCopy;
+ shadow::ReleaseShadowCopyFct releaseShadowCopy;
Zstring shadowVol;
ShadowHandle backupHandle;
};
-
-
-shadow::CreateShadowCopyFct ShadowCopy::ShadowVolume::createShadowCopy;
-shadow::ReleaseShadowCopyFct ShadowCopy::ShadowVolume::releaseShadowCopy;
//#############################################################################################################
Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
{
- using namespace zen;
-
wchar_t volumeNameRaw[1000];
if (!::GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName,
diff --git a/shared/shadow.h b/shared/shadow.h
index edea4377..aff5b437 100644
--- a/shared/shadow.h
+++ b/shared/shadow.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SHADOW_H_INCLUDED
#define SHADOW_H_INCLUDED
diff --git a/shared/shell_execute.h b/shared/shell_execute.h
index 2cabbed1..64797eff 100644
--- a/shared/shell_execute.h
+++ b/shared/shell_execute.h
@@ -3,20 +3,20 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef EXECUTE_HEADER_23482134578134134
#define EXECUTE_HEADER_23482134578134134
-#include <wx/string.h>
#include <wx/msgdlg.h>
#ifdef FFS_WIN
-#include "string_tools.h"
#include "last_error.h"
+#include "string_tools.h"
#include "i18n.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
#elif defined FFS_LINUX
+#include <stdlib.h>
#include <wx/utils.h>
#endif
@@ -69,7 +69,7 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC)
if (!::ShellExecuteEx(&execInfo)) //__inout LPSHELLEXECUTEINFO lpExecInfo
{
- wxString errorMsg = _("Invalid commandline: \"%x\"");
+ wxString errorMsg = _("Invalid commandline: %x");
wxString cmdFmt = wxString(L"\nFile: ") + filename + L"\nArg: " + arguments;
errorMsg.Replace(L"%x", cmdFmt);
@@ -87,10 +87,26 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC)
}
#elif defined FFS_LINUX
- //by default wxExecute uses a zero sized dummy window as a hack to keep focus which leaves a useless empty icon in ALT-TAB list
- //=> use wxEXEC_NODISABLE and roll our own window disabler! (see comment in app.cpp: void *wxGUIAppTraits::BeforeChildWaitLoop())
- wxWindowDisabler dummy; //disables all top level windows
- wxExecute(command, (type == EXEC_TYPE_ASYNC ? wxEXEC_ASYNC : wxEXEC_SYNC) | wxEXEC_NODISABLE);
+ if (type == EXEC_TYPE_SYNC)
+ {
+ int rv = ::system(utf8CvrtTo<std::string>(command).c_str()); //do NOT use std::system as its documentation says nothing about "WEXITSTATUS(rv)", ect...
+ if (rv == -1 || WEXITSTATUS(rv) == 127) //http://linux.die.net/man/3/system "In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127)"
+ {
+ wxString errorMsg = _("Invalid commandline: %x");
+ replace(errorMsg, L"%x", L"\n" + command);
+ wxMessageBox(errorMsg);
+ return;
+ }
+ }
+ else
+ {
+ // ! unfortunately it seems there is no way on Linux to get a failure notification for calling an invalid commandline asynchronously !
+
+ //by default wxExecute uses a zero sized dummy window as a hack to keep focus which leaves a useless empty icon in ALT-TAB list
+ //=> use wxEXEC_NODISABLE and roll our own window disabler! (see comment in app.cpp: void *wxGUIAppTraits::BeforeChildWaitLoop())
+ wxWindowDisabler dummy; //disables all top level windows
+ wxExecute(command, wxEXEC_ASYNC | wxEXEC_NODISABLE);
+ }
#endif
}
}
diff --git a/shared/standard_paths.cpp b/shared/standard_paths.cpp
index 928dedcc..c2d79516 100644
--- a/shared/standard_paths.cpp
+++ b/shared/standard_paths.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "standard_paths.h"
#include <wx/stdpaths.h>
#include "string_conv.h"
diff --git a/shared/standard_paths.h b/shared/standard_paths.h
index faafe263..708a377d 100644
--- a/shared/standard_paths.h
+++ b/shared/standard_paths.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef STANDARDPATHS_H_INCLUDED
#define STANDARDPATHS_H_INCLUDED
diff --git a/shared/string_conv.h b/shared/string_conv.h
index 477dda8c..976080fb 100644
--- a/shared/string_conv.h
+++ b/shared/string_conv.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef STRINGCONV_H_INCLUDED
#define STRINGCONV_H_INCLUDED
diff --git a/shared/symlink_target.h b/shared/symlink_target.h
index e3a75f81..ef7b2275 100644
--- a/shared/symlink_target.h
+++ b/shared/symlink_target.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef SYMLINK_WIN_H_INCLUDED
#define SYMLINK_WIN_H_INCLUDED
diff --git a/shared/taskbar.cpp b/shared/taskbar.cpp
index 969f4bb0..005df705 100644
--- a/shared/taskbar.cpp
+++ b/shared/taskbar.cpp
@@ -5,16 +5,24 @@
// **************************************************************************
//
#include "taskbar.h"
+
+#ifdef FFS_WIN
#include "Taskbar_Seven/taskbar.h"
#include "dll_loader.h"
#include "build_info.h"
#include "assert_static.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
+#elif defined HAVE_UBUNTU_UNITY
+#include <unity/unity/unity.h>
+#endif
+
using namespace util;
-using namespace tbseven;
+#ifdef FFS_WIN
+using namespace tbseven;
+
namespace
{
bool windows7TaskbarAvailable()
@@ -45,7 +53,7 @@ std::wstring getTaskBarDllName()
//########################################################################################################
-class TaskbarProgress::Pimpl //throw (TaskbarNotAvailable)
+class Taskbar::Pimpl //throw (TaskbarNotAvailable)
{
public:
Pimpl(const wxTopLevelWindow& window) :
@@ -60,29 +68,26 @@ public:
throw TaskbarNotAvailable();
}
- ~Pimpl()
- {
- setStatus(STATUS_NOPROGRESS);
- }
+ ~Pimpl() { setStatus(STATUS_NOPROGRESS); }
void setStatus(Status status)
{
TaskBarStatus tbSevenStatus = tbseven::STATUS_NORMAL;
switch (status)
{
- case TaskbarProgress::STATUS_NOPROGRESS:
+ case Taskbar::STATUS_NOPROGRESS:
tbSevenStatus = tbseven::STATUS_NOPROGRESS;
break;
- case TaskbarProgress::STATUS_INDETERMINATE:
+ case Taskbar::STATUS_INDETERMINATE:
tbSevenStatus = tbseven::STATUS_INDETERMINATE;
break;
- case TaskbarProgress::STATUS_NORMAL:
+ case Taskbar::STATUS_NORMAL:
tbSevenStatus = tbseven::STATUS_NORMAL;
break;
- case TaskbarProgress::STATUS_ERROR:
+ case Taskbar::STATUS_ERROR:
tbSevenStatus = tbseven::STATUS_ERROR;
break;
- case TaskbarProgress::STATUS_PAUSED:
+ case Taskbar::STATUS_PAUSED:
tbSevenStatus = tbseven::STATUS_PAUSED;
break;
}
@@ -96,23 +101,80 @@ public:
}
private:
- void* assocWindow;
+ void* assocWindow; //HWND
const SetStatusFct setStatus_;
const SetProgressFct setProgress_;
};
-//########################################################################################################
+#elif defined HAVE_UBUNTU_UNITY //Ubuntu unity
+namespace
+{
+const char FFS_DESKTOP_FILE[] = "freefilesync.desktop";
+}
-TaskbarProgress::TaskbarProgress(const wxTopLevelWindow& window) : pimpl_(new Pimpl(window)) {}
+class Taskbar::Pimpl //throw (TaskbarNotAvailable)
+{
+public:
+ Pimpl(const wxTopLevelWindow& window) :
+ tbEntry(unity_launcher_entry_get_for_desktop_id(FFS_DESKTOP_FILE))
+ //tbEntry(unity_launcher_entry_get_for_app_uri("application://freefilesync.desktop"))
+ {
+ if (!tbEntry)
+ throw TaskbarNotAvailable();
+ }
-TaskbarProgress::~TaskbarProgress() {} //std::unique_ptr ...
+ ~Pimpl() { setStatus(STATUS_NOPROGRESS); } //it seems UnityLauncherEntry* does not need destruction
-void TaskbarProgress::setStatus(Status status)
-{
- pimpl_->setStatus(status);
-}
+ void setStatus(Status status)
+ {
+ switch (status)
+ {
+ case Taskbar::STATUS_ERROR:
+ unity_launcher_entry_set_urgent(tbEntry, true);
+ break;
-void TaskbarProgress::setProgress(size_t current, size_t total)
+ case Taskbar::STATUS_NOPROGRESS:
+ case Taskbar::STATUS_INDETERMINATE:
+ unity_launcher_entry_set_urgent(tbEntry, false);
+ unity_launcher_entry_set_progress_visible(tbEntry, false);
+ break;
+
+ case Taskbar::STATUS_NORMAL:
+ unity_launcher_entry_set_urgent(tbEntry, false);
+ unity_launcher_entry_set_progress_visible(tbEntry, true);
+ break;
+
+ case Taskbar::STATUS_PAUSED:
+ unity_launcher_entry_set_urgent (tbEntry, false);
+ break;
+ }
+ }
+
+ void setProgress(size_t current, size_t total)
+ {
+ unity_launcher_entry_set_progress(tbEntry, total == 0 ? 0 : double(current) / total);
+ }
+
+private:
+ UnityLauncherEntry* tbEntry;
+};
+
+
+#else //no taskbar support yet
+class Taskbar::Pimpl
{
- pimpl_->setProgress(current, total);
-}
+public:
+ Pimpl(const wxTopLevelWindow& window) { throw TaskbarNotAvailable(); }
+ void setStatus(Status status) {}
+ void setProgress(size_t current, size_t total) {}
+
+};
+#endif
+
+
+//########################################################################################################
+Taskbar::Taskbar(const wxTopLevelWindow& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable
+Taskbar::~Taskbar() {} //std::unique_ptr ...
+
+void Taskbar::setStatus(Status status) { pimpl_->setStatus(status); }
+void Taskbar::setProgress(size_t current, size_t total) { pimpl_->setProgress(current, total); }
diff --git a/shared/taskbar.h b/shared/taskbar.h
index 90a76d13..54e0a431 100644
--- a/shared/taskbar.h
+++ b/shared/taskbar.h
@@ -3,28 +3,32 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef TASKBARPROGRESS_H_INCLUDED
#define TASKBARPROGRESS_H_INCLUDED
-#ifndef FFS_WIN
-use in windows build only!
-#endif
-
#include <wx/toplevel.h>
#include <memory>
+/*
+Windows 7; show progress in windows superbar via ITaskbarList3 Interface (http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx)
+
+Ubuntu: use Unity interface (optional)
+
+Define HAVE_UBUNTU_UNITY and set:
+ Compiler flag: `pkg-config --cflags unity`
+ Linker flag: `pkg-config --libs unity`
+*/
namespace util
{
class TaskbarNotAvailable {};
-//show progress in windows superbar via ITaskbarList3 Interface (http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx)
-class TaskbarProgress
+class Taskbar
{
public:
- TaskbarProgress(const wxTopLevelWindow& window); //throw TaskbarNotAvailable()
- ~TaskbarProgress();
+ Taskbar(const wxTopLevelWindow& window); //throw TaskbarNotAvailable()
+ ~Taskbar();
enum Status
{
diff --git a/shared/toggle_button.cpp b/shared/toggle_button.cpp
index 511822b1..24f74bc7 100644
--- a/shared/toggle_button.cpp
+++ b/shared/toggle_button.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "toggle_button.h"
void ToggleButton::init(const wxBitmap& activeBmp,
diff --git a/shared/toggle_button.h b/shared/toggle_button.h
index 6613fdd4..f333ca24 100644
--- a/shared/toggle_button.h
+++ b/shared/toggle_button.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef TOGGLEBUTTON_H_INCLUDED
#define TOGGLEBUTTON_H_INCLUDED
diff --git a/shared/util.cpp b/shared/util.cpp
index faa4074c..d780d683 100644
--- a/shared/util.cpp
+++ b/shared/util.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "util.h"
#include "zstring.h"
#include "i18n.h"
diff --git a/shared/util.h b/shared/util.h
index 25762ce7..0e08280e 100644
--- a/shared/util.h
+++ b/shared/util.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
diff --git a/shared/warn_static.h b/shared/warn_static.h
new file mode 100644
index 00000000..bb4f4a6f
--- /dev/null
+++ b/shared/warn_static.h
@@ -0,0 +1,35 @@
+// **************************************************************************
+// * 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 WARN_STATIC_HEADER_08724567834560832745
+#define WARN_STATIC_HEADER_08724567834560832745
+
+/*
+Portable Compile-Time Warning
+-----------------------------
+Usage:
+ warn_static("my message")
+*/
+
+#ifdef _MSC_VER
+#define MAKE_STRING_SUB(NUM) #NUM
+#define MAKE_STRING(NUM) MAKE_STRING_SUB(NUM)
+
+#define warn_static(TXT) \
+__pragma(message (__FILE__ "(" MAKE_STRING(__LINE__) "): Warning: " ## TXT))
+
+#elif defined __GNUC__
+#define LOKI_CONCAT( X, Y ) LOKI_CONCAT_SUB( X, Y )
+#define LOKI_CONCAT_SUB( X, Y ) X##Y
+
+#define warn_static(TXT) \
+typedef int STATIC_WARNING __attribute__ ((deprecated)); \
+enum { LOKI_CONCAT(warn_static_dummy_value, __LINE__) = sizeof(STATIC_WARNING) };
+#endif
+
+
+#endif //WARN_STATIC_HEADER_08724567834560832745 \ No newline at end of file
diff --git a/shared/wx_choice_enum.h b/shared/wx_choice_enum.h
index 9f832394..e8fbeead 100644
--- a/shared/wx_choice_enum.h
+++ b/shared/wx_choice_enum.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef WX_CHOICE_ENUM_H_INCLUDED
#define WX_CHOICE_ENUM_H_INCLUDED
diff --git a/shared/wx_timespan.h b/shared/wx_timespan.h
index 108327bf..2e566927 100644
--- a/shared/wx_timespan.h
+++ b/shared/wx_timespan.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef WX_TIMESPAN_CTRL_HEADER_INCLUDED
#define WX_TIMESPAN_CTRL_HEADER_INCLUDED
diff --git a/shared/xml_base.cpp b/shared/xml_base.cpp
index cd9f58a6..c7c92401 100644
--- a/shared/xml_base.cpp
+++ b/shared/xml_base.cpp
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "xml_base.h"
#include <file_handling.h>
#include <string_conv.h>
@@ -13,12 +13,14 @@
using namespace zen;
+//loadXmlDocument vs loadStream:
+//1. better error reporting
+//2. quick exit if (potentially large) input file is not an XML
void xmlAccess::loadXmlDocument(const wxString& filename, XmlDoc& doc) //throw FfsXmlError()
{
std::string stream;
try
{
- 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...)
@@ -31,6 +33,7 @@ void xmlAccess::loadXmlDocument(const wxString& filename, XmlDoc& doc) //throw F
throw FfsXmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
+ const zen::UInt64 fs = zen::getFilesize(toZ(filename)); //throw (FileError)
stream.resize(to<size_t>(fs));
FileInput inputFile(toZ(filename)); //throw (FileError);
diff --git a/shared/xml_base.h b/shared/xml_base.h
index 6a47fcf2..37d79863 100644
--- a/shared/xml_base.h
+++ b/shared/xml_base.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef XMLBASE_H_INCLUDED
#define XMLBASE_H_INCLUDED
diff --git a/shared/xml_error.h b/shared/xml_error.h
index ffd6af8b..6e17670a 100644
--- a/shared/xml_error.h
+++ b/shared/xml_error.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef XMLERROR_H_INCLUDED
#define XMLERROR_H_INCLUDED
diff --git a/shared/zbase.h b/shared/zbase.h
index 6d9ac578..55bc0d96 100644
--- a/shared/zbase.h
+++ b/shared/zbase.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef Z_BASE_H_INCLUDED
#define Z_BASE_H_INCLUDED
@@ -12,6 +12,7 @@
#include <sstream>
#include <algorithm>
#include <string_tools.h>
+#include <boost/detail/atomic_count.hpp>
/*
Allocator Policy:
@@ -101,24 +102,17 @@ private:
size_t capacity; //allocated size without null-termination
};
- static Descriptor* descr(T* ptr)
- {
- return reinterpret_cast<Descriptor*>(ptr) - 1;
- }
-
- static const Descriptor* descr(const T* ptr)
- {
- return reinterpret_cast<const Descriptor*>(ptr) - 1;
- }
+ static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
+ static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
};
template <typename T, //Character Type
class AP> //Allocator Policy
-class StorageRefCount : public AP
+class StorageRefCountThreadSafe : public AP
{
protected:
- ~StorageRefCount() {}
+ ~StorageRefCountThreadSafe() {}
static T* create(size_t size)
{
@@ -132,10 +126,7 @@ protected:
assert(minCapacity >= size);
Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(T)));
-
- newDescr->refCount = 1;
- newDescr->length = size;
- newDescr->capacity = newCapacity;
+ new (newDescr) Descriptor(1, size, newCapacity);
return reinterpret_cast<T*>(newDescr + 1);
}
@@ -150,7 +141,10 @@ protected:
static void destroy(T* ptr)
{
if (--descr(ptr)->refCount == 0)
+ {
+ descr(ptr)->~Descriptor();
AP::deallocate(descr(ptr));
+ }
}
static bool canWrite(const T* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
@@ -173,26 +167,23 @@ protected:
private:
struct Descriptor
{
- size_t refCount;
+ Descriptor(long rc, size_t len, size_t cap) : refCount(rc), length(len), capacity(cap) {}
+
+ boost::detail::atomic_count refCount; //practically no perf loss: ~0.2%! (FFS comparison)
size_t length;
size_t capacity; //allocated size without null-termination
};
- static Descriptor* descr(T* ptr)
- {
- return reinterpret_cast<Descriptor*>(ptr) - 1;
- }
-
- static const Descriptor* descr(const T* ptr)
- {
- return reinterpret_cast<const Descriptor*>(ptr) - 1;
- }
+ static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
+ static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
};
-template <class T, //Character Type
- template <class, class> class SP = StorageRefCount, //Storage Policy
- class AP = AllocatorOptimalSpeed> //Allocator Policy
+//perf note: interstingly StorageDeepCopy and StorageRefCountThreadSafe show same performance in FFS comparison
+
+template <class T, //Character Type
+ template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy
+ class AP = AllocatorOptimalSpeed> //Allocator Policy
class Zbase : public SP<T, AP>
{
public:
@@ -200,6 +191,7 @@ public:
Zbase(const T* source); //implicit conversion from a C-string
Zbase(const T* source, size_t length);
Zbase(const Zbase& source);
+ Zbase(Zbase&& tmp);
explicit Zbase(T source); //dangerous if implicit: T buffer[]; Zbase name = buffer; ups...
//allow explicit construction from different string type, prevent ambiguity via SFINAE
template <class S> explicit Zbase(const S& other, typename S::value_type = 0);
@@ -261,6 +253,7 @@ public:
void push_back(T val); //STL access
Zbase& operator=(const Zbase& source);
+ Zbase& operator=(Zbase&& tmp);
Zbase& operator=(const T* source);
Zbase& operator=(T source);
Zbase& operator+=(const Zbase& other);
@@ -380,6 +373,14 @@ Zbase<T, SP, AP>::Zbase(const Zbase<T, SP, AP>& source)
template <class T, template <class, class> class SP, class AP>
+inline
+Zbase<T, SP, AP>::Zbase(Zbase<T, SP, AP>&& tmp)
+{
+ rawStr = this->clone(tmp.rawStr); //for a ref-counting string there probably isn't a faster way, even with r-value references
+}
+
+
+template <class T, template <class, class> class SP, class AP>
template <class S>
inline
Zbase<T, SP, AP>::Zbase(const S& other, typename S::value_type)
@@ -827,6 +828,15 @@ Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const Zbase<T, SP, AP>& source)
template <class T, template <class, class> class SP, class AP>
inline
+Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(Zbase<T, SP, AP>&& tmp)
+{
+ swap(tmp);
+ return *this;
+}
+
+
+template <class T, template <class, class> class SP, class AP>
+inline
Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const T* source)
{
return assign(source, zen::cStringLength(source));
diff --git a/shared/zstring.cpp b/shared/zstring.cpp
index 2955ec3e..e1df17ee 100644
--- a/shared/zstring.cpp
+++ b/shared/zstring.cpp
@@ -3,9 +3,10 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#include "zstring.h"
#include <stdexcept>
+#include <boost/thread/once.hpp>
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
@@ -52,6 +53,12 @@ LeakChecker& LeakChecker::instance()
return inst;
}
+//caveat: function scope static initialization is not thread-safe in VS 2010! => make sure to call at app start!
+namespace
+{
+struct Dummy { Dummy() { LeakChecker::instance(); }} blah;
+}
+
std::string LeakChecker::rawMemToString(const void* ptr, size_t size)
{
@@ -113,7 +120,10 @@ int z_impl::compareFilenamesWin(const wchar_t* a, const wchar_t* b, size_t sizeA
LPCWSTR lpString2,
int cchCount2,
BOOL bIgnoreCase);
- static const CompareStringOrdinalFunc ordinalCompare = util::getDllFun<CompareStringOrdinalFunc>(L"kernel32.dll", "CompareStringOrdinal");
+ static CompareStringOrdinalFunc ordinalCompare = NULL; //caveat: function scope static initialization is not thread-safe in VS 2010!
+ static boost::once_flag once = BOOST_ONCE_INIT;
+ boost::call_once(once, []() { ordinalCompare = util::getDllFun<CompareStringOrdinalFunc>(L"kernel32.dll", "CompareStringOrdinal"); });
+
if (ordinalCompare != NULL) //this additional test has no noticeable performance impact
{
diff --git a/shared/zstring.h b/shared/zstring.h
index 841fb8a2..3b4837db 100644
--- a/shared/zstring.h
+++ b/shared/zstring.h
@@ -3,7 +3,7 @@
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
-//
+
#ifndef ZSTRING_H_INCLUDED
#define ZSTRING_H_INCLUDED
@@ -11,8 +11,8 @@
#include <cstring> //strcmp()
#ifndef NDEBUG
+#include "boost_thread_wrap.h" //include <boost/thread.hpp>
#include <map>
-#include <wx/thread.h>
#endif
@@ -22,7 +22,7 @@ class LeakChecker //small test for memory leaks
public:
void insert(const void* ptr, size_t size)
{
- wxCriticalSectionLocker dummy(lockActStrings);
+ boost::lock_guard<boost::mutex> dummy(lockActStrings);
if (activeStrings.find(ptr) != activeStrings.end())
reportProblem(std::string("Fatal Error: New memory points into occupied space: ") + rawMemToString(ptr, size));
@@ -31,8 +31,7 @@ public:
void remove(const void* ptr)
{
- wxCriticalSectionLocker dummy(lockActStrings);
-
+ boost::lock_guard<boost::mutex> dummy(lockActStrings);
if (activeStrings.find(ptr) == activeStrings.end())
reportProblem(std::string("Fatal Error: No memory available for deallocation at this location!"));
@@ -50,7 +49,7 @@ private:
static std::string rawMemToString(const void* ptr, size_t size);
void reportProblem(const std::string& message); //throw (std::logic_error)
- wxCriticalSection lockActStrings;
+ boost::mutex lockActStrings;
typedef std::map<const void*, size_t> VoidPtrSizeMap;
VoidPtrSizeMap activeStrings;
};
@@ -106,7 +105,6 @@ template <template <class, class> class SP, class AP>
void MakeUpper(Zbase<wchar_t, SP, AP>& str);
#endif
-
#ifdef FFS_WIN //Windows stores filenames in wide character format
typedef wchar_t Zchar;
#define Zstr(x) L ## x
@@ -121,8 +119,8 @@ const Zchar FILE_NAME_SEPARATOR = '/';
#error define platform you are in: FFS_WIN or FFS_LINUX
#endif
-//"The reason for all the fuss above" (Loki/SmartPtr)
-typedef Zbase<Zchar, StorageRefCount, AllocatorFreeStoreChecked> Zstring; //for use with file names
+//"The reason for all the fuss above" - Loki/SmartPtr
+typedef Zbase<Zchar, StorageRefCountThreadSafe, AllocatorFreeStoreChecked> Zstring; //for use with file names
bgstack15