1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
26 #include <MUtils/Global.h>
27 #include <MUtils/OSSupport.h>
31 #include <QReadWriteLock>
38 ///////////////////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////////////////
42 //Robert Jenkins' 96 bit Mix Function
43 static unsigned int mix_function(const unsigned int x, const unsigned int y, const unsigned int z)
49 a=a-b; a=a-c; a=a^(c >> 13);
50 b=b-c; b=b-a; b=b^(a << 8 );
51 c=c-a; c=c-b; c=c^(b >> 13);
52 a=a-b; a=a-c; a=a^(c >> 12);
53 b=b-c; b=b-a; b=b^(a << 16);
54 c=c-a; c=c-b; c=c^(b >> 5 );
55 a=a-b; a=a-c; a=a^(c >> 3 );
56 b=b-c; b=b-a; b=b^(a << 10);
57 c=c-a; c=c-b; c=c^(b >> 15);
62 void MUtils::seed_rand(void)
64 qsrand(mix_function(clock(), time(NULL), _getpid()));
67 quint32 MUtils::next_rand32(void)
69 quint32 rnd = 0xDEADBEEF;
78 for(size_t i = 0; i < sizeof(quint32); i++)
80 rnd = (rnd << 8) ^ qrand();
86 quint64 MUtils::next_rand64(void)
88 return (quint64(next_rand32()) << 32) | quint64(next_rand32());
91 QString MUtils::rand_str(const bool &bLong)
95 return QString::number(next_rand64(), 16).rightJustified(16, QLatin1Char('0'));
97 return QString("%1%2").arg(rand_str(false), rand_str(false));
100 ///////////////////////////////////////////////////////////////////////////////
102 ///////////////////////////////////////////////////////////////////////////////
104 static QReadWriteLock g_temp_folder_lock;
105 static QFile *g_temp_folder_file;
106 static QString *g_temp_folder_path = NULL;
108 #define INIT_TEMP_FOLDER_RAND(OUT_PTR, FILE_PTR, BASE_DIR) do \
110 for(int _i = 0; _i < 128; _i++) \
112 const QString _randDir = QString("%1/%2").arg((BASE_DIR), rand_str()); \
113 if(!QDir(_randDir).exists()) \
115 *(OUT_PTR) = try_init_folder(_randDir, (FILE_PTR)); \
116 if(!(OUT_PTR)->isEmpty()) break; \
122 static QString try_init_folder(const QString &folderPath, QFile *&lockFile)
124 static const char *TEST_DATA = "Lorem ipsum dolor sit amet, consectetur, adipisci velit!";
126 bool success = false;
128 const QFileInfo folderInfo(folderPath);
129 const QDir folderDir(folderInfo.absoluteFilePath());
131 //Remove existing lock file
135 MUTILS_DELETE(lockFile);
138 //Create folder, if it does *not* exist yet
139 if(!folderDir.exists())
141 for(int i = 0; i < 16; i++)
143 if(folderDir.mkpath(".")) break;
147 //Make sure folder exists now *and* is writable
148 if(folderDir.exists())
150 const QByteArray testData = QByteArray(TEST_DATA);
151 for(int i = 0; i < 32; i++)
153 lockFile = new QFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(MUtils::rand_str())));
154 if(lockFile->open(QIODevice::ReadWrite | QIODevice::Truncate))
156 if(lockFile->write(testData) >= testData.size())
162 MUTILS_DELETE(lockFile);
167 return (success ? folderDir.canonicalPath() : QString());
170 const QString &MUtils::temp_folder(void)
172 QReadLocker readLock(&g_temp_folder_lock);
174 //Already initialized?
175 if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
177 return (*g_temp_folder_path);
180 //Obtain the write lock to initilaize
182 QWriteLocker writeLock(&g_temp_folder_lock);
184 //Still uninitilaized?
185 if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
187 return (*g_temp_folder_path);
190 //Create the string, if not done yet
191 if(!g_temp_folder_path)
193 g_temp_folder_path = new QString();
196 g_temp_folder_path->clear();
198 //Try the %TMP% or %TEMP% directory first
199 QString tempPath = try_init_folder(QDir::temp().absolutePath(), g_temp_folder_file);
200 if(!tempPath.isEmpty())
202 INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
205 //Otherwise create TEMP folder in %LOCALAPPDATA% or %SYSTEMROOT%
206 if(g_temp_folder_path->isEmpty())
208 qWarning("%%TEMP%% directory not found -> trying fallback mode now!");
209 static const OS::known_folder_t folderId[2] = { OS::FOLDER_LOCALAPPDATA, OS::FOLDER_SYSTROOT_DIR };
210 for(size_t id = 0; (g_temp_folder_path->isEmpty() && (id < 2)); id++)
212 const QString &knownFolder = OS::known_folder(folderId[id]);
213 if(!knownFolder.isEmpty())
215 tempPath = try_init_folder(QString("%1/Temp").arg(knownFolder), g_temp_folder_file);
216 if(!tempPath.isEmpty())
218 INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
224 //Failed to create TEMP folder?
225 if(g_temp_folder_path->isEmpty())
227 qFatal("Temporary directory could not be initialized !!!");
230 return (*g_temp_folder_path);