OSDN Git Service

Improved temp_folder() function + we will now clean-up the TEMP folder on application...
authorLoRd_MuldeR <mulder2@gmx.de>
Tue, 25 Nov 2014 01:17:11 +0000 (02:17 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Tue, 25 Nov 2014 01:17:11 +0000 (02:17 +0100)
MUtilities_VS2013.vcxproj
MUtilities_VS2013.vcxproj.filters
include/MUtils/Global.h
include/MUtils/Version.h
src/CriticalSection_Win32.h
src/DirLocker.h [new file with mode: 0644]
src/Global.cpp
src/OSSupport_Win32.cpp
src/Version.cpp

index 3ab810e..794fdc5 100644 (file)
@@ -27,6 +27,7 @@
     <ClInclude Include="include\MUtils\Global.h" />
     <ClInclude Include="include\MUtils\KeccakHash.h" />
     <ClInclude Include="include\MUtils\OSSupport.h" />
+    <ClInclude Include="src\DirLocker.h" />
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
       <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)"</Command>
       <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp"</Message>
index bde2a89..e231689 100644 (file)
@@ -59,6 +59,9 @@
     <ClInclude Include="include\MUtils\KeccakHash.h">
       <Filter>Public Headers</Filter>
     </ClInclude>
+    <ClInclude Include="src\DirLocker.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
index 797604d..c235b88 100644 (file)
@@ -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<const wchar_t*>((STR).utf16()))
-#define MUTILS_QSTR2QUTF8(STR) ((STR).toUtf8().constData())
-#define MUTILS_WCHAR2QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
+//String conversion macros
+#define MUTILS_WCHR(STR) (reinterpret_cast<const wchar_t*>((STR).utf16()))
+#define MUTILS_UTF8(STR) ((STR).toUtf8().constData())
+#define MUTILS_QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
+
+//Boolean helper
+#define MUTILS_BOOL2STR(X) ((X) ? "1" : "0")
index dfae3e9..a0d9e7f 100644 (file)
 
 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__;
index e6f7b84..78bc2d4 100644 (file)
 // CRITICAL SECTION
 ///////////////////////////////////////////////////////////////////////////////
 
-/*
- * wrapper for native Win32 critical sections
- */
-class CriticalSection
+namespace MUtils
 {
-public:
-       inline CriticalSection(void)
+       namespace Internal
        {
-               InitializeCriticalSection(&m_win32criticalSection);
-       }
+               /*
+                * wrapper for native Win32 critical sections
+                */
+               class CriticalSection
+               {
+               public:
+                       inline CriticalSection(void)
+                       {
+                               InitializeCriticalSection(&m_win32criticalSection);
+                       }
 
-       inline ~CriticalSection(void)
-       {
-               DeleteCriticalSection(&m_win32criticalSection);
-       }
+                       inline ~CriticalSection(void)
+                       {
+                               DeleteCriticalSection(&m_win32criticalSection);
+                       }
 
-       inline void enter(void)
-       {
-               EnterCriticalSection(&m_win32criticalSection);
-       }
+                       inline void enter(void)
+                       {
+                               EnterCriticalSection(&m_win32criticalSection);
+                       }
 
-       inline bool tryEnter(void)
-       {
-               return TryEnterCriticalSection(&m_win32criticalSection);
-       }
+                       inline bool tryEnter(void)
+                       {
+                               return TryEnterCriticalSection(&m_win32criticalSection);
+                       }
 
-       inline void leave(void)
-       {
-               LeaveCriticalSection(&m_win32criticalSection);
-       }
+                       inline void leave(void)
+                       {
+                               LeaveCriticalSection(&m_win32criticalSection);
+                       }
 
-protected:
-       CRITICAL_SECTION 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;
-       }
+               /*
               * 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 ~CSLocker(void)
+                       {
+                               forceUnlock();
+                       }
 
-       inline void forceUnlock(void)
-       {
-               if(m_locked)
-               {
-                       m_criticalSection.leave();
-                       m_locked = false;
-               }
+                       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 (file)
index 0000000..f4a683f
--- /dev/null
@@ -0,0 +1,112 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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 <MUtils/Global.h>
+
+//StdLib
+#include <stdexcept>
+
+//Qt
+#include <QString>
+#include <QFile>
+
+///////////////////////////////////////////////////////////////////////////////
+// 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<QFile> m_lockFile;
+               };
+
+               const char *const DirLock::TEST_DATA = "7QtDxPWotHGQYv1xHyQHFKjTB5u5VYKHE20NMDAgLRYoy16CZN7mEYijbjCJpORnoBbtHCzqyy1a6BLCMMiTUZpLzgjg4qnN505egUBqk3wMhPsYjFpkng9i37mWd1iF";
+       }
+}
index b560432..e889041 100644 (file)
 #define _CRT_RAND_S 1
 #endif
 
+//MUtils
 #include <MUtils/Global.h>
 #include <MUtils/OSSupport.h>
+#include "DirLocker.h"
 
 //Qt
 #include <QDir>
@@ -102,9 +104,8 @@ QString MUtils::rand_str(const bool &bLong)
 // TEMP FOLDER
 ///////////////////////////////////////////////////////////////////////////////
 
-static QScopedPointer<QFile>   g_temp_folder_file;
-static QScopedPointer<QString> g_temp_folder_path;
-static QReadWriteLock          g_temp_folder_lock;
+static QScopedPointer<MUtils::Internal::DirLock> 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();
                                }
                        }
                }
@@ -198,6 +194,65 @@ const QString &MUtils::temp_folder(void)
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// 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
 ///////////////////////////////////////////////////////////////////////////////
 
index c8145d5..1b9698d 100644 (file)
@@ -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)
 {
index a5a40b5..e958ce9 100644 (file)
@@ -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]);
 }