From 2086c3dde6a28d34d6439d7080aad2353c0c7eaa Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Tue, 25 Nov 2014 02:17:11 +0100 Subject: [PATCH] Improved temp_folder() function + we will now clean-up the TEMP folder on application exit. --- MUtilities_VS2013.vcxproj | 1 + MUtilities_VS2013.vcxproj.filters | 3 + include/MUtils/Global.h | 26 ++++-- include/MUtils/Version.h | 12 +-- src/CriticalSection_Win32.h | 132 ++++++++++++++++-------------- src/DirLocker.h | 112 +++++++++++++++++++++++++ src/Global.cpp | 113 ++++++++++++++++++------- src/OSSupport_Win32.cpp | 8 +- src/Version.cpp | 8 +- 9 files changed, 305 insertions(+), 110 deletions(-) create mode 100644 src/DirLocker.h diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj index 3ab810e..794fdc5 100644 --- a/MUtilities_VS2013.vcxproj +++ b/MUtilities_VS2013.vcxproj @@ -27,6 +27,7 @@ + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters index bde2a89..e231689 100644 --- a/MUtilities_VS2013.vcxproj.filters +++ b/MUtilities_VS2013.vcxproj.filters @@ -59,6 +59,9 @@ Public Headers + + Header Files + diff --git a/include/MUtils/Global.h b/include/MUtils/Global.h index 797604d..c235b88 100644 --- a/include/MUtils/Global.h +++ b/include/MUtils/Global.h @@ -50,17 +50,24 @@ class QProcess; //Check Debug Flags #if defined(_DEBUG) || defined(DEBUG) || (!defined(NDEBUG)) -# define MUTILS_DEBUG 1 +# define MUTILS_DEBUG (1) # if defined(NDEBUG) || defined(QT_NO_DEBUG) || (!defined(QT_DEBUG)) # error Inconsistent DEBUG flags have been detected! # endif #else -# define MUTILS_DEBUG 0 +# define MUTILS_DEBUG (0) # if (!defined(NDEBUG)) || (!defined(QT_NO_DEBUG)) || defined(QT_DEBUG) # error Inconsistent DEBUG flags have been detected! # endif #endif +//Check CPU options +#if defined(_MSC_VER) && (!defined(_M_X64)) && defined(_M_IX86_FP) + #if (_M_IX86_FP != 0) + #error We should not enabled SSE or SSE2 in release builds! + #endif +#endif + /////////////////////////////////////////////////////////////////////////////// namespace MUtils @@ -77,9 +84,14 @@ namespace MUtils MUTILS_API quint32 next_rand32(void); MUTILS_API quint64 next_rand64(void); + //Remove File/Dir + MUTILS_API bool remove_file(const QString &fileName); + MUTILS_API bool remove_directory(const QString &folderPath); + //Version MUTILS_API const char* mutils_build_date(void); MUTILS_API const char* mutils_build_time(void); + //Internal namespace Internal { @@ -110,6 +122,10 @@ while(0) } \ while(0) -#define MUTILS_QSTR2WCHAR(STR) (reinterpret_cast((STR).utf16())) -#define MUTILS_QSTR2QUTF8(STR) ((STR).toUtf8().constData()) -#define MUTILS_WCHAR2QSTR(STR) (QString::fromUtf16(reinterpret_cast((STR)))) +//String conversion macros +#define MUTILS_WCHR(STR) (reinterpret_cast((STR).utf16())) +#define MUTILS_UTF8(STR) ((STR).toUtf8().constData()) +#define MUTILS_QSTR(STR) (QString::fromUtf16(reinterpret_cast((STR)))) + +//Boolean helper +#define MUTILS_BOOL2STR(X) ((X) ? "1" : "0") diff --git a/include/MUtils/Version.h b/include/MUtils/Version.h index dfae3e9..a0d9e7f 100644 --- a/include/MUtils/Version.h +++ b/include/MUtils/Version.h @@ -31,17 +31,17 @@ namespace MUtils { - class MUTILS_API Version + class Version { public: //Get Build Date - static const QDate build_date(const char *const date_str = build_date_raw()); + MUTILS_API static const QDate build_date(const char *const date_str = build_date_raw()); //Get Build Time - static const QTime build_time(const char *const time_str = build_time_raw()); + MUTILS_API static const QTime build_time(const char *const time_str = build_time_raw()); //Compiler detection - static const char *const compiler_version(void) + MUTILS_API static const char *const compiler_version(void) { #if defined(__INTEL_COMPILER) #if (__INTEL_COMPILER >= 1500) @@ -109,7 +109,7 @@ namespace MUtils } //Architecture detection - static const char *const compiler_arch(void) + MUTILS_API static const char *const compiler_arch(void) { #if defined(_M_X64) static const char *const COMPILER_ARCH = "x64"; @@ -130,7 +130,7 @@ namespace MUtils return RAW_BUILD_DATE; } - //Raw Build date + //Raw Build time static const char *const build_time_raw(void) { static const char *const RAW_BUILD_TIME = __TIME__; diff --git a/src/CriticalSection_Win32.h b/src/CriticalSection_Win32.h index e6f7b84..78bc2d4 100644 --- a/src/CriticalSection_Win32.h +++ b/src/CriticalSection_Win32.h @@ -29,70 +29,76 @@ // CRITICAL SECTION /////////////////////////////////////////////////////////////////////////////// -/* - * wrapper for native Win32 critical sections - */ -class CriticalSection +namespace MUtils { -public: - inline CriticalSection(void) + namespace Internal { - InitializeCriticalSection(&m_win32criticalSection); - } - - inline ~CriticalSection(void) - { - DeleteCriticalSection(&m_win32criticalSection); - } - - inline void enter(void) - { - EnterCriticalSection(&m_win32criticalSection); - } - - inline bool tryEnter(void) - { - return TryEnterCriticalSection(&m_win32criticalSection); - } - - inline void leave(void) - { - LeaveCriticalSection(&m_win32criticalSection); - } - -protected: - CRITICAL_SECTION m_win32criticalSection; -}; - -/* - * RAII-style critical section locker - */ -class CSLocker -{ -public: - inline CSLocker(CriticalSection &criticalSection) - : - m_locked(false), - m_criticalSection(criticalSection) - { - m_criticalSection.enter(); - m_locked = true; - } - - inline ~CSLocker(void) - { - forceUnlock(); - } - - inline void forceUnlock(void) - { - if(m_locked) + /* + * wrapper for native Win32 critical sections + */ + class CriticalSection { - m_criticalSection.leave(); - m_locked = false; - } + public: + inline CriticalSection(void) + { + InitializeCriticalSection(&m_win32criticalSection); + } + + inline ~CriticalSection(void) + { + DeleteCriticalSection(&m_win32criticalSection); + } + + inline void enter(void) + { + EnterCriticalSection(&m_win32criticalSection); + } + + inline bool tryEnter(void) + { + return TryEnterCriticalSection(&m_win32criticalSection); + } + + inline void leave(void) + { + LeaveCriticalSection(&m_win32criticalSection); + } + + protected: + CRITICAL_SECTION m_win32criticalSection; + }; + + /* + * RAII-style critical section locker + */ + class CSLocker + { + public: + inline CSLocker(CriticalSection &criticalSection) + : + m_locked(false), + m_criticalSection(criticalSection) + { + m_criticalSection.enter(); + m_locked = true; + } + + inline ~CSLocker(void) + { + forceUnlock(); + } + + inline void forceUnlock(void) + { + if(m_locked) + { + m_criticalSection.leave(); + m_locked = false; + } + } + protected: + volatile bool m_locked; + CriticalSection &m_criticalSection; + }; } -protected: - volatile bool m_locked; - CriticalSection &m_criticalSection; -}; +} diff --git a/src/DirLocker.h b/src/DirLocker.h new file mode 100644 index 0000000..f4a683f --- /dev/null +++ b/src/DirLocker.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//MUtils +#include + +//StdLib +#include + +//Qt +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// Directory Locker +/////////////////////////////////////////////////////////////////////////////// + +namespace MUtils +{ + namespace Internal + { + class DirLockException : public std::runtime_error + { + public: + DirLockException(const char *const message) + : + std::runtime_error(message) + { + } + }; + + class DirLock + { + public: + DirLock(const QString dirPath) + : + m_dirPath(dirPath) + { + if(m_dirPath.isEmpty()) + { + throw DirLockException("Path must not be empty!"); + } + const QByteArray testData = QByteArray(TEST_DATA); + bool okay = false; + for(int i = 0; i < 32; i++) + { + m_lockFile.reset(new QFile(QString("%1/~%2.lck").arg(m_dirPath, MUtils::rand_str()))); + if(m_lockFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) + { + if(m_lockFile->write(testData) >= testData.size()) + { + okay = true; + break; + } + m_lockFile->remove(); + } + } + if(!okay) + { + throw DirLockException("Locking has failed!"); + } + } + + ~DirLock(void) + { + if(!m_lockFile.isNull()) + { + m_lockFile->remove(); + } + for(int i = 0; i < 8; i++) + { + if(MUtils::remove_directory(m_dirPath)) + { + break; + } + } + } + + inline const QString &path(void) const + { + return m_dirPath; + } + + private: + static const char *const TEST_DATA; + const QString m_dirPath; + QScopedPointer m_lockFile; + }; + + const char *const DirLock::TEST_DATA = "7QtDxPWotHGQYv1xHyQHFKjTB5u5VYKHE20NMDAgLRYoy16CZN7mEYijbjCJpORnoBbtHCzqyy1a6BLCMMiTUZpLzgjg4qnN505egUBqk3wMhPsYjFpkng9i37mWd1iF"; + } +} diff --git a/src/Global.cpp b/src/Global.cpp index b560432..e889041 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -23,8 +23,10 @@ #define _CRT_RAND_S 1 #endif +//MUtils #include #include +#include "DirLocker.h" //Qt #include @@ -102,9 +104,8 @@ QString MUtils::rand_str(const bool &bLong) // TEMP FOLDER /////////////////////////////////////////////////////////////////////////////// -static QScopedPointer g_temp_folder_file; -static QScopedPointer g_temp_folder_path; -static QReadWriteLock g_temp_folder_lock; +static QScopedPointer g_temp_folder_file; +static QReadWriteLock g_temp_folder_lock; static QString try_create_subfolder(const QString &baseDir, const QString &postfix) { @@ -120,29 +121,26 @@ static QString try_create_subfolder(const QString &baseDir, const QString &postf return QString(); } -static QString try_init_temp_folder(const QString &baseDir) +static MUtils::Internal::DirLock *try_init_temp_folder(const QString &baseDir) { - static const char *TEST_DATA = "Lorem ipsum dolor sit amet, consectetur, adipisci velit!"; - - QString tempPath = try_create_subfolder(baseDir, MUtils::rand_str()); + const QString tempPath = try_create_subfolder(baseDir, MUtils::rand_str()); if(!tempPath.isEmpty()) { - const QByteArray testData = QByteArray(TEST_DATA); for(int i = 0; i < 32; i++) { - g_temp_folder_file.reset(new QFile(QString("%1/~%2.lck").arg(tempPath, MUtils::rand_str()))); - if(g_temp_folder_file->open(QIODevice::ReadWrite | QIODevice::Truncate)) + MUtils::Internal::DirLock *lockFile = NULL; + try { - if(g_temp_folder_file->write(testData) >= testData.size()) - { - return tempPath; - } - g_temp_folder_file->remove(); + lockFile = new MUtils::Internal::DirLock(tempPath); + return lockFile; + } + catch(MUtils::Internal::DirLockException&) + { + /*ignore error and try again*/ } } } - - return QString(); + return NULL; } const QString &MUtils::temp_folder(void) @@ -150,9 +148,9 @@ const QString &MUtils::temp_folder(void) QReadLocker readLock(&g_temp_folder_lock); //Already initialized? - if((!g_temp_folder_path.isNull()) && (!g_temp_folder_path->isEmpty())) + if(!g_temp_folder_file.isNull()) { - return (*g_temp_folder_path.data()); + return g_temp_folder_file->path(); } //Obtain the write lock to initilaize @@ -160,17 +158,16 @@ const QString &MUtils::temp_folder(void) QWriteLocker writeLock(&g_temp_folder_lock); //Still uninitilaized? - if((!g_temp_folder_path.isNull()) && (!g_temp_folder_path->isEmpty())) + if(!g_temp_folder_file.isNull()) { - return (*g_temp_folder_path.data()); + return g_temp_folder_file->path(); } //Try the %TMP% or %TEMP% directory first - QString tempPath = try_init_temp_folder(QDir::tempPath()); - if(!tempPath.isEmpty()) + if(MUtils::Internal::DirLock *lockFile = try_init_temp_folder(QDir::tempPath())) { - g_temp_folder_path.reset(new QString(tempPath)); - return (*g_temp_folder_path.data()); + g_temp_folder_file.reset(lockFile); + return lockFile->path(); } qWarning("%%TEMP%% directory not found -> trying fallback mode now!"); @@ -183,11 +180,10 @@ const QString &MUtils::temp_folder(void) const QString tempRoot = try_create_subfolder(knownFolder, QLatin1String("TEMP")); if(!tempRoot.isEmpty()) { - tempPath = try_init_temp_folder(tempRoot); - if(!tempPath.isEmpty()) + if(MUtils::Internal::DirLock *lockFile = try_init_temp_folder(tempRoot)) { - g_temp_folder_path.reset(new QString(tempPath)); - return (*g_temp_folder_path.data()); + g_temp_folder_file.reset(lockFile); + return lockFile->path(); } } } @@ -197,6 +193,65 @@ const QString &MUtils::temp_folder(void) return (*((QString*)NULL)); } +/////////////////////////////////////////////////////////////////////////////// +// REMOVE DIRECTORY / FILE +/////////////////////////////////////////////////////////////////////////////// + +bool MUtils::remove_file(const QString &fileName) +{ + QFileInfo fileInfo(fileName); + if(!(fileInfo.exists() && fileInfo.isFile())) + { + return true; + } + + for(int i = 0; i < 32; i++) + { + QFile file(fileName); + file.setPermissions(QFile::ReadOther | QFile::WriteOther); + if(file.remove()) + { + return true; + } + } + + qWarning("Could not delete \"%s\"", MUTILS_UTF8(fileName)); + return false; +} + +bool MUtils::remove_directory(const QString &folderPath) +{ + QDir folder(folderPath); + if(!folder.exists()) + { + return true; + } + + const QFileInfoList entryList = folder.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden); + for(int i = 0; i < entryList.count(); i++) + { + if(entryList.at(i).isDir()) + { + remove_directory(entryList.at(i).canonicalFilePath()); + } + else + { + remove_file(entryList.at(i).canonicalFilePath()); + } + } + + for(int i = 0; i < 32; i++) + { + if(folder.rmdir(".")) + { + return true; + } + } + + qWarning("Could not rmdir \"%s\"", MUTILS_UTF8(folderPath)); + return false; +} + /////////////////////////////////////////////////////////////////////////////// // PROCESS UTILS /////////////////////////////////////////////////////////////////////////////// diff --git a/src/OSSupport_Win32.cpp b/src/OSSupport_Win32.cpp index c8145d5..1b9698d 100644 --- a/src/OSSupport_Win32.cpp +++ b/src/OSSupport_Win32.cpp @@ -153,7 +153,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id) if(g_known_folders_fpGetKnownFolderPath(s_folders[folderId].guid, KF_FLAG_CREATE, NULL, &path) == S_OK) { //MessageBoxW(0, path, L"SHGetKnownFolderPath", MB_TOPMOST); - QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_WCHAR2QSTR(path))); + QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_QSTR(path))); if(folderTemp.exists()) { folderPath = folderTemp.canonicalPath(); @@ -167,7 +167,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id) if(g_known_folders_fpGetFolderPath(NULL, s_folders[folderId].csidl | CSIDL_FLAG_CREATE, NULL, NULL, path.data()) == S_OK) { //MessageBoxW(0, path, L"SHGetFolderPathW", MB_TOPMOST); - QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_WCHAR2QSTR(path.data()))); + QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_QSTR(path.data()))); if(folderTemp.exists()) { folderPath = folderTemp.canonicalPath(); @@ -259,8 +259,8 @@ int MUtils::OS::network_status(void) // FATAL EXIT /////////////////////////////////////////////////////////////////////////////// -static CriticalSection g_fatal_exit_lock; -static volatile bool g_fatal_exit_flag = true; +static MUtils::Internal::CriticalSection g_fatal_exit_lock; +static volatile bool g_fatal_exit_flag = true; static DWORD WINAPI fatal_exit_helper(LPVOID lpParameter) { diff --git a/src/Version.cpp b/src/Version.cpp index a5a40b5..e958ce9 100644 --- a/src/Version.cpp +++ b/src/Version.cpp @@ -58,18 +58,19 @@ const QDate MUtils::Version::build_date(const char *const date_str) ok = ok && (_snscanf(&date_str[0x0], 3, "%s", &month_s) == 1); ok = ok && ((date[1] = month2int(month_s)) > 0); - ok = ok && (_snscanf(&date_str[0x4], 2, "%d", &date[0]) == 1); - ok = ok && (_snscanf(&date_str[0x7], 4, "%d", &date[2]) == 1); + ok = ok && (_snscanf(&date_str[0x4], 2, "%d", &date[2]) == 1); + ok = ok && (_snscanf(&date_str[0x7], 4, "%d", &date[0]) == 1); if(!ok) { MUTILS_THROW("Internal error: Date format could not be recognized!"); } + //qWarning("MUtils::Version::build_date: y=%d, m=%d, d=%d", date[0], date[1], date[2]); return QDate(date[0], date[1], date[2]); } -static const QTime build_time(const char *const time_str) +const QTime MUtils::Version::build_time(const char *const time_str) { bool ok = true; int time[3] = {0, 0, 0}; @@ -83,6 +84,7 @@ static const QTime build_time(const char *const time_str) MUTILS_THROW("Internal error: Time format could not be recognized!"); } + //qWarning("MUtils::Version::build_date: h=%d, m=%d, s=%d", time[0], time[1], time[2]); return QTime(time[0], time[1], time[2]); }