OSDN Git Service

Implemented temp_folder() function.
authorLoRd_MuldeR <mulder2@gmx.de>
Fri, 21 Nov 2014 17:15:09 +0000 (18:15 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Fri, 21 Nov 2014 17:15:09 +0000 (18:15 +0100)
include/MUtils/Global.h
src/Global.cpp

index a7b0dc8..c929451 100644 (file)
@@ -32,4 +32,19 @@ namespace MUtils
        QString rand_str(const bool &bLong = false);
        quint32 next_rand32(void);
        quint64 next_rand64(void);
+
+       //Temp Folder
+       const QString &temp_folder(void);
 }
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MUTILS_DELETE(PTR) do \
+{ \
+       if((PTR)) \
+       { \
+               delete (PTR); \
+               (PTR) = NULL; \
+       } \
+} \
+while(0)
index eba0258..042cbcf 100644 (file)
 
 #include <MUtils/Global.h>
 
+//Qt
+#include <QDir>
+#include <QReadWriteLock>
+
 //CRT
 #include <cstdlib>
 #include <ctime>
@@ -91,3 +95,136 @@ QString MUtils::rand_str(const bool &bLong)
        }
        return QString("%1%2").arg(rand_str(false), rand_str(false));
 }
+
+///////////////////////////////////////////////////////////////////////////////
+// TEMP FOLDER
+///////////////////////////////////////////////////////////////////////////////
+
+static QReadWriteLock g_temp_folder_lock;
+static QFile *g_temp_folder_file;
+static QString *g_temp_folder_path = NULL;
+
+#define INIT_TEMP_FOLDER_RAND(OUT_PTR, FILE_PTR, BASE_DIR) do \
+{ \
+       for(int _i = 0; _i < 128; _i++) \
+       { \
+               const QString _randDir = QString("%1/%2").arg((BASE_DIR), rand_str()); \
+               if(!QDir(_randDir).exists()) \
+               { \
+                       *(OUT_PTR) = try_init_folder(_randDir, (FILE_PTR)); \
+                       if(!(OUT_PTR)->isEmpty()) break; \
+               } \
+       } \
+} \
+while(0)
+
+static QString try_init_folder(const QString &folderPath, QFile *&lockFile)
+{
+       static const char *TEST_DATA = "Lorem ipsum dolor sit amet, consectetur, adipisci velit!";
+       
+       bool success = false;
+
+       const QFileInfo folderInfo(folderPath);
+       const QDir folderDir(folderInfo.absoluteFilePath());
+
+       //Remove existing lock file
+       if(lockFile)
+       {
+               lockFile->remove();
+               MUTILS_DELETE(lockFile);
+       }
+
+       //Create folder, if it does *not* exist yet
+       if(!folderDir.exists())
+       {
+               for(int i = 0; i < 16; i++)
+               {
+                       if(folderDir.mkpath(".")) break;
+               }
+       }
+
+       //Make sure folder exists now *and* is writable
+       if(folderDir.exists())
+       {
+               const QByteArray testData = QByteArray(TEST_DATA);
+               for(int i = 0; i < 32; i++)
+               {
+                       lockFile = new QFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(MUtils::rand_str())));
+                       if(lockFile->open(QIODevice::ReadWrite | QIODevice::Truncate))
+                       {
+                               if(lockFile->write(testData) >= testData.size())
+                               {
+                                       success = true;
+                                       break;
+                               }
+                               lockFile->remove();
+                               MUTILS_DELETE(lockFile);
+                       }
+               }
+       }
+
+       return (success ? folderDir.canonicalPath() : QString());
+}
+
+const QString &MUtils::temp_folder(void)
+{
+       QReadLocker readLock(&g_temp_folder_lock);
+
+       //Already initialized?
+       if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
+       {
+               return (*g_temp_folder_path);
+       }
+
+       //Obtain the write lock to initilaize
+       readLock.unlock();
+       QWriteLocker writeLock(&g_temp_folder_lock);
+       
+       //Still uninitilaized?
+       if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
+       {
+               return (*g_temp_folder_path);
+       }
+
+       //Create the string, if not done yet
+       if(!g_temp_folder_path)
+       {
+               g_temp_folder_path = new QString();
+       }
+       
+       g_temp_folder_path->clear();
+
+       //Try the %TMP% or %TEMP% directory first
+       QString tempPath = try_init_folder(QDir::temp().absolutePath(), g_temp_folder_file);
+       if(!tempPath.isEmpty())
+       {
+               INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
+       }
+
+       //Otherwise create TEMP folder in %LOCALAPPDATA% or %SYSTEMROOT%
+       if(g_temp_folder_path->isEmpty())
+       {
+               qWarning("%%TEMP%% directory not found -> trying fallback mode now!");
+               static const lamexp_known_folder_t folderId[2] = { lamexp_folder_localappdata, lamexp_folder_systroot_dir };
+               for(size_t id = 0; (g_lamexp_temp_folder.path->isEmpty() && (id < 2)); id++)
+               {
+                       const QString &knownFolder = lamexp_known_folder(folderId[id]);
+                       if(!knownFolder.isEmpty())
+                       {
+                               tempPath = try_init_folder(QString("%1/Temp").arg(knownFolder));
+                               if(!tempPath.isEmpty())
+                               {
+                                       INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
+                               }
+                       }
+               }
+       }
+
+       //Failed to create TEMP folder?
+       if(g_temp_folder_path->isEmpty())
+       {
+               qFatal("Temporary directory could not be initialized !!!");
+       }
+       
+       return (*g_temp_folder_path);
+}