From 9f22ae6385ac1349ab4af2b37fe93492322b1e8a Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Fri, 21 Nov 2014 18:15:09 +0100 Subject: [PATCH] Implemented temp_folder() function. --- include/MUtils/Global.h | 15 +++++ src/Global.cpp | 137 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/include/MUtils/Global.h b/include/MUtils/Global.h index a7b0dc8..c929451 100644 --- a/include/MUtils/Global.h +++ b/include/MUtils/Global.h @@ -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) diff --git a/src/Global.cpp b/src/Global.cpp index eba0258..042cbcf 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -25,6 +25,10 @@ #include +//Qt +#include +#include + //CRT #include #include @@ -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); +}