From 1714af0a4d978405b1c839c93e68aea5bd8ebf25 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sun, 30 Aug 2015 13:47:08 +0200 Subject: [PATCH] Refactored the "LockedFile" class + moved hash computation to a separate class, for clarity. --- LameXP_VS2013.vcxproj | 2 + LameXP_VS2013.vcxproj.filters | 6 + LameXP_VS2015.vcxproj | 2 + LameXP_VS2015.vcxproj.filters | 6 + doc/Changelog.html | 4 +- doc/Changelog.md | 2 +- etc/NSIS/setup.nsi | 1 + src/Config.h | 2 +- src/Dialog_About.cpp | 2 +- src/FileHash.cpp | 68 +++++++++++ src/FileHash.h | 37 ++++++ src/Global_Tools.cpp | 5 + src/LockedFile.cpp | 220 ++++++++++++++++++---------------- src/LockedFile.h | 4 +- src/Thread_Initialization.cpp | 68 ++++++++--- 15 files changed, 298 insertions(+), 131 deletions(-) create mode 100644 src/FileHash.cpp create mode 100644 src/FileHash.h diff --git a/LameXP_VS2013.vcxproj b/LameXP_VS2013.vcxproj index 3735619b..a78e1623 100644 --- a/LameXP_VS2013.vcxproj +++ b/LameXP_VS2013.vcxproj @@ -314,6 +314,7 @@ copy /Y "$(SolutionDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\i + @@ -427,6 +428,7 @@ copy /Y "$(SolutionDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\i $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" diff --git a/LameXP_VS2013.vcxproj.filters b/LameXP_VS2013.vcxproj.filters index c175cdb1..83259fb8 100644 --- a/LameXP_VS2013.vcxproj.filters +++ b/LameXP_VS2013.vcxproj.filters @@ -421,6 +421,9 @@ Generated Files\MOC + + Source Files\Misc + @@ -555,6 +558,9 @@ Header Files\Misc + + Header Files\Misc + diff --git a/LameXP_VS2015.vcxproj b/LameXP_VS2015.vcxproj index cbe358fd..78f564c6 100644 --- a/LameXP_VS2015.vcxproj +++ b/LameXP_VS2015.vcxproj @@ -314,6 +314,7 @@ copy /Y "$(SolutionDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\i + @@ -427,6 +428,7 @@ copy /Y "$(SolutionDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\i $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" diff --git a/LameXP_VS2015.vcxproj.filters b/LameXP_VS2015.vcxproj.filters index c175cdb1..83259fb8 100644 --- a/LameXP_VS2015.vcxproj.filters +++ b/LameXP_VS2015.vcxproj.filters @@ -421,6 +421,9 @@ Generated Files\MOC + + Source Files\Misc + @@ -555,6 +558,9 @@ Header Files\Misc + + Header Files\Misc + diff --git a/doc/Changelog.html b/doc/Changelog.html index e08b6625..48c5422b 100644 --- a/doc/Changelog.html +++ b/doc/Changelog.html @@ -84,12 +84,12 @@
  • Upgraded build environment to Microsoft Visual Studio 2013 with Update-5
  • Updated Qt runtime libraries to v4.8.7 Final (2015-05-25), compiled with MSVC 12.0
  • -
  • Added Hungarian translation, contributed by Zityi's Translator Team
  • +>
  • Added optional support for the libfdk-aac encoder, using the fdkaac front-end by nu774
  • Added detection of the 64-Bit version of QAAC encoder, requires 64-Bit Apple Application Support
  • Added enhanced file renaming option: Default file extensions can now be overwritten
  • diff --git a/doc/Changelog.md b/doc/Changelog.md index 69b62838..caf93798 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -6,7 +6,7 @@ * Upgraded build environment to Microsoft Visual Studio 2013 with Update-5 * Updated Qt runtime libraries to v4.8.7 Final (2015-05-25), compiled with MSVC 12.0 -* Added Hungarian translation, contributed by Zityi's Translator Team +* Added Hungarian translation, contributed by Zityi's Translator Team <> * Added optional support for the *libfdk-aac* encoder, using the [fdkaac](https://github.com/nu774/fdkaac) front-end by nu774 * Added detection of the *64-Bit* version of QAAC encoder, requires 64-Bit Apple Application Support * Added enhanced file renaming option: Default file extensions can now be overwritten diff --git a/etc/NSIS/setup.nsi b/etc/NSIS/setup.nsi index b7e21bfd..5080352a 100644 --- a/etc/NSIS/setup.nsi +++ b/etc/NSIS/setup.nsi @@ -526,6 +526,7 @@ FunctionEnd Delete ${options} "$INSTDIR\vcruntime*.dll" Delete ${options} "$INSTDIR\vccorlib*.dll" + RMDir /r ${options} "$INSTDIR\cache" RMDir /r ${options} "$INSTDIR\img" RMDir /r ${options} "$INSTDIR\imageformats" RMDir /r ${options} "$INSTDIR\redist" diff --git a/src/Config.h b/src/Config.h index bb8b39ed..c7a23997 100644 --- a/src/Config.h +++ b/src/Config.h @@ -35,7 +35,7 @@ #define VER_LAMEXP_MINOR_LO 2 #define VER_LAMEXP_TYPE Beta #define VER_LAMEXP_PATCH 6 -#define VER_LAMEXP_BUILD 1798 +#define VER_LAMEXP_BUILD 1800 #define VER_LAMEXP_CONFG 1700 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Dialog_About.cpp b/src/Dialog_About.cpp index 420d3bfc..7b2e069d 100644 --- a/src/Dialog_About.cpp +++ b/src/Dialog_About.cpp @@ -815,7 +815,7 @@ void AboutDialog::initSoftwareTab(void) tr("dcaenc"), "dcaenc.exe", "????-??-??", tr("Copyright (c) 2008-2011 Alexander E. Patrakov. Distributed under the LGPL."), - "http://gitorious.org/dtsenc/dtsenc/trees/master" + "https://gitlab.com/patrakov/dcaenc" ); moreAboutText += makeToolText ( diff --git a/src/FileHash.cpp b/src/FileHash.cpp new file mode 100644 index 00000000..405d3eb9 --- /dev/null +++ b/src/FileHash.cpp @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2015 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version, but always including the *additional* +// restrictions defined in the "License.txt" file. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#include "FileHash.h" + +//MUtils +#include +#include + +static const char *g_blnk = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; +static const char *g_seed = "c375d83b4388329408dfcbb4d9a065b6e06d28272f25ef299c70b506e26600af79fd2f866ae24602daf38f25c9d4b7e1"; +static const char *g_salt = "ee9f7bdabc170763d2200a7e3030045aafe380011aefc1730e547e9244c62308aac42a976feeca224ba553de0c4bb883"; + +QByteArray FileHash::computeHash(QFile &file) +{ + QByteArray hash = QByteArray::fromHex(g_blnk); + + if(file.isOpen() && file.reset()) + { + MUtils::Hash::Keccak keccak; + + const QByteArray data = file.readAll(); + const QByteArray seed = QByteArray::fromHex(g_seed); + const QByteArray salt = QByteArray::fromHex(g_salt); + + if(keccak.init(MUtils::Hash::Keccak::hb384)) + { + bool ok = true; + ok = ok && keccak.addData(seed); + ok = ok && keccak.addData(data); + ok = ok && keccak.addData(salt); + if(ok) + { + const QByteArray digest = keccak.finalize(); + if(!digest.isEmpty()) hash = digest.toHex(); + } + } + } + + return hash; +} + +void FileHash::selfTest(void) +{ + if(!MUtils::Hash::Keccak::selfTest()) + { + MUTILS_THROW("QKeccakHash self-test has failed!"); + } +} diff --git a/src/FileHash.h b/src/FileHash.h new file mode 100644 index 00000000..adbbc634 --- /dev/null +++ b/src/FileHash.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2015 LoRd_MuldeR +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version, but always including the *additional* +// restrictions defined in the "License.txt" file. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include + +class FileHash +{ +public: + static QByteArray computeHash(QFile &file); + static void selfTest(void); +private: + FileHash() {} + ~FileHash() {}; +}; + diff --git a/src/Global_Tools.cpp b/src/Global_Tools.cpp index 799bd68e..7a74dd39 100644 --- a/src/Global_Tools.cpp +++ b/src/Global_Tools.cpp @@ -94,6 +94,11 @@ void lamexp_tools_register(const QString &toolName, LockedFile *const file, cons { QWriteLocker writeLock(&g_lamexp_tools_lock); + if(!file) + { + MUTILS_THROW("lamexp_register_tool: Tool file must not be NULL!"); + } + if(g_lamexp_tools_data.isNull()) { g_lamexp_tools_data.reset(new tool_hash_t()); diff --git a/src/LockedFile.cpp b/src/LockedFile.cpp index 24770e71..0c455028 100644 --- a/src/LockedFile.cpp +++ b/src/LockedFile.cpp @@ -21,11 +21,13 @@ /////////////////////////////////////////////////////////////////////////////// #include "LockedFile.h" + +//Internal #include "Global.h" +#include "FileHash.h" //MUtils #include -#include #include //Qt @@ -35,6 +37,7 @@ #include #include +//CRT #include #include #include @@ -67,63 +70,19 @@ static void CLOSE_HANDLE(HANDLE &h) /////////////////////////////////////////////////////////////////////////////// -static const char *g_blnk = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; -static const char *g_seed = "c375d83b4388329408dfcbb4d9a065b6e06d28272f25ef299c70b506e26600af79fd2f866ae24602daf38f25c9d4b7e1"; -static const char *g_salt = "ee9f7bdabc170763d2200a7e3030045aafe380011aefc1730e547e9244c62308aac42a976feeca224ba553de0c4bb883"; - -QByteArray LockedFile::fileHash(QFile &file) +static __forceinline void doWriteOutput(QFile &outFile, const QResource *const resource) { - QByteArray hash = QByteArray::fromHex(g_blnk); - - if(file.isOpen() && file.reset()) - { - MUtils::Hash::Keccak keccak; - - const QByteArray data = file.readAll(); - const QByteArray seed = QByteArray::fromHex(g_seed); - const QByteArray salt = QByteArray::fromHex(g_salt); - - if(keccak.init(MUtils::Hash::Keccak::hb384)) - { - bool ok = true; - ok = ok && keccak.addData(seed); - ok = ok && keccak.addData(data); - ok = ok && keccak.addData(salt); - if(ok) - { - const QByteArray digest = keccak.finalize(); - if(!digest.isEmpty()) hash = digest.toHex(); - } - } - } - - return hash; -} - -/////////////////////////////////////////////////////////////////////////////// - -LockedFile::LockedFile(QResource *const resource, const QString &outPath, const QByteArray &expectedHash, const bool bOwnsFile) -: - m_bOwnsFile(bOwnsFile), - m_filePath(QFileInfo(outPath).absoluteFilePath()) -{ - m_fileDescriptor = -1; - HANDLE fileHandle = NULL; - - //Make sure the resource is valid - if(!(resource->isValid() && resource->data())) - { - MUTILS_THROW_FMT("The resource at %p is invalid!", resource); - } - - QFile outFile(m_filePath); - - //Open output file for(int i = 0; i < 64; i++) { - if(outFile.open(QIODevice::WriteOnly)) break; - if(!i) qWarning("Failed to open file on first attemp, retrying..."); - Sleep(100); + if(outFile.open(QIODevice::WriteOnly)) + { + break; + } + if(i == 0) + { + qWarning("Failed to open file on first attemp, retrying..."); + } + Sleep(25); } //Write data to file @@ -142,40 +101,68 @@ LockedFile::LockedFile(QResource *const resource, const QString &outPath, const //Close file after it has been written outFile.close(); +} - //Now lock the file! +static __forceinline void doValidateFileExists(const QString &filePath) +{ + QFileInfo existingFileInfo(filePath); + existingFileInfo.setCaching(false); + + //Make sure the file exists, before we try to lock it + if((!existingFileInfo.exists()) || (!existingFileInfo.isFile()) || filePath.isEmpty()) + { + MUTILS_THROW_FMT("File '%s' does not exist!", MUTILS_UTF8(filePath)); + } +} + +static __forceinline void doLockFile(HANDLE &fileHandle, const QString &filePath, QFile *const outFile) +{ for(int i = 0; i < 64; i++) { - fileHandle = CreateFileW(MUTILS_WCHR(QDir::toNativeSeparators(m_filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); - if(VALID_HANDLE(fileHandle)) break; - if(!i) qWarning("Failed to lock file on first attemp, retrying..."); - Sleep(100); + fileHandle = CreateFileW(MUTILS_WCHR(QDir::toNativeSeparators(filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + if(VALID_HANDLE(fileHandle)) + { + break; + } + if(i == 0) + { + qWarning("Failed to lock file on first attemp, retrying..."); + } + Sleep(25); } //Locked successfully? if(!VALID_HANDLE(fileHandle)) { - QFile::remove(QFileInfo(outFile).canonicalFilePath()); - MUTILS_THROW_FMT("File '%s' could not be locked!", MUTILS_UTF8(QFileInfo(m_filePath).fileName())); + if(outFile) + { + QFile::remove(QFileInfo(*outFile).canonicalFilePath()); + } + MUTILS_THROW_FMT("File '%s' could not be locked!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } +} - //Get file descriptor - m_fileDescriptor = _open_osfhandle(reinterpret_cast(fileHandle), _O_RDONLY | _O_BINARY); - if(m_fileDescriptor < 0) +static __forceinline void doInitFileDescriptor(const HANDLE &fileHandle, int &fileDescriptor) +{ + fileDescriptor = _open_osfhandle(reinterpret_cast(fileHandle), _O_RDONLY | _O_BINARY); + if(fileDescriptor < 0) { MUTILS_THROW_FMT("Failed to obtain C Runtime file descriptor!"); } +} +static __forceinline void doValidateHash(HANDLE &fileHandle, const int &fileDescriptor, const QByteArray &expectedHash, const QString &filePath) +{ QFile checkFile; //Now re-open the file for reading if(g_useFileDescrForQFile) { - checkFile.open(m_fileDescriptor, QIODevice::ReadOnly); + checkFile.open(fileDescriptor, QIODevice::ReadOnly); } else { - checkFile.setFileName(m_filePath); + checkFile.setFileName(filePath); for(int i = 0; i < 64; i++) { if(checkFile.open(QIODevice::ReadOnly)) break; @@ -187,12 +174,12 @@ LockedFile::LockedFile(QResource *const resource, const QString &outPath, const //Opened successfully if(!checkFile.isOpen()) { - QFile::remove(m_filePath); - MUTILS_THROW_FMT("File '%s' could not be read!", MUTILS_UTF8(QFileInfo(m_filePath).fileName())); + QFile::remove(filePath); + MUTILS_THROW_FMT("File '%s' could not be read!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } //Verify file contents - const QByteArray hash = fileHash(checkFile); + const QByteArray hash = FileHash::computeHash(checkFile); checkFile.close(); //Compare hashes @@ -200,11 +187,62 @@ LockedFile::LockedFile(QResource *const resource, const QString &outPath, const { qWarning("\nFile checksum error:\n A = %s\n B = %s\n", expectedHash.constData(), hash.constData()); CLOSE_HANDLE(fileHandle); - QFile::remove(m_filePath); - MUTILS_THROW_FMT("File '%s' is corruputed, take care!", MUTILS_UTF8(QFileInfo(m_filePath).fileName())); + QFile::remove(filePath); + MUTILS_THROW_FMT("File '%s' is corruputed, take care!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } } +/////////////////////////////////////////////////////////////////////////////// + +LockedFile::LockedFile(QResource *const resource, const QString &outPath, const QByteArray &expectedHash, const bool bOwnsFile) +: + m_bOwnsFile(bOwnsFile), + m_filePath(QFileInfo(outPath).absoluteFilePath()) +{ + m_fileDescriptor = -1; + HANDLE fileHandle = NULL; + + //Make sure the resource is valid + if(!(resource->isValid() && resource->data())) + { + MUTILS_THROW_FMT("The resource at %p is invalid!", resource); + } + + //Write data to output file + QFile outFile(m_filePath); + doWriteOutput(outFile, resource); + + //Now lock the file! + doLockFile(fileHandle, m_filePath, &outFile); + + //Get file descriptor + doInitFileDescriptor(fileHandle, m_fileDescriptor); + + //Validate file hash + doValidateHash(fileHandle, m_fileDescriptor, expectedHash, m_filePath); +} + +LockedFile::LockedFile(const QString &filePath, const QByteArray &expectedHash, const bool bOwnsFile) +: + m_bOwnsFile(bOwnsFile), + m_filePath(QFileInfo(filePath).absoluteFilePath()) +{ + m_fileDescriptor = -1; + HANDLE fileHandle = NULL; + + //Make sure the file exists, before we try to lock it + doValidateFileExists(m_filePath); + + //Now lock the file! + doLockFile(fileHandle, m_filePath, NULL); + + //Get file descriptor + doInitFileDescriptor(fileHandle, m_fileDescriptor); + + //Validate file hash + doValidateHash(fileHandle, m_fileDescriptor, expectedHash, m_filePath); +} + LockedFile::LockedFile(const QString &filePath, const bool bOwnsFile) : m_bOwnsFile(bOwnsFile), @@ -212,37 +250,15 @@ LockedFile::LockedFile(const QString &filePath, const bool bOwnsFile) { m_fileDescriptor = -1; HANDLE fileHandle = NULL; - - QFileInfo existingFileInfo(filePath); - existingFileInfo.setCaching(false); //Make sure the file exists, before we try to lock it - if((!existingFileInfo.exists()) || (!existingFileInfo.isFile()) || m_filePath.isEmpty()) - { - MUTILS_THROW_FMT("File '%s' does not exist!", MUTILS_UTF8(filePath)); - } - - //Now lock the file - for(int i = 0; i < 64; i++) - { - fileHandle = CreateFileW(MUTILS_WCHR(QDir::toNativeSeparators(m_filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); - if(VALID_HANDLE(fileHandle)) break; - if(!i) qWarning("Failed to lock file on first attemp, retrying..."); - Sleep(100); - } + doValidateFileExists(m_filePath); - //Locked successfully? - if(!VALID_HANDLE(fileHandle)) - { - MUTILS_THROW_FMT("File '%s' could not be locked!", MUTILS_UTF8(QFileInfo(m_filePath).fileName())); - } + //Now lock the file! + doLockFile(fileHandle, m_filePath, NULL); //Get file descriptor - m_fileDescriptor = _open_osfhandle(reinterpret_cast(fileHandle), _O_RDONLY | _O_BINARY); - if(m_fileDescriptor < 0) - { - MUTILS_THROW_FMT("Failed to obtain C Runtime file descriptor!"); - } + doInitFileDescriptor(fileHandle, m_fileDescriptor); } LockedFile::~LockedFile(void) @@ -269,11 +285,3 @@ const QString &LockedFile::filePath() { return m_filePath; } - -void LockedFile::selfTest() -{ - if(!MUtils::Hash::Keccak::selfTest()) - { - MUTILS_THROW("QKeccakHash self-test has failed!"); - } -} diff --git a/src/LockedFile.h b/src/LockedFile.h index 77b49ff6..e5eb42e9 100644 --- a/src/LockedFile.h +++ b/src/LockedFile.h @@ -31,14 +31,12 @@ class LockedFile { public: LockedFile(QResource *const resource, const QString &outPath, const QByteArray &expectedHash = QByteArray(), const bool bOwnsFile = true); + LockedFile(const QString &filePath, const QByteArray &expectedHash, const bool bOwnsFile = false); LockedFile(const QString &filePath, const bool bOwnsFile = false); ~LockedFile(void); const QString &filePath(); - static void selfTest(); - static QByteArray fileHash(QFile &file); - private: const bool m_bOwnsFile; const QString m_filePath; diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp index 2598b65d..39162446 100644 --- a/src/Thread_Initialization.cpp +++ b/src/Thread_Initialization.cpp @@ -26,6 +26,7 @@ #define LAMEXP_INC_TOOLS 1 #include "Tools.h" #include "LockedFile.h" +#include "FileHash.h" #include "Tool_Abstract.h" //MUtils @@ -49,6 +50,9 @@ #include #include +/* enable custom tools? */ +static const bool ENABLE_CUSTOM_TOOLS = true; + /* helper macros */ #define PRINT_CPU_TYPE(X) case X: qDebug("Selected CPU is: " #X) #define MAKE_REGEXP(STR) (((STR) && ((STR)[0])) ? QRegExp((STR)) : QRegExp()) @@ -208,28 +212,58 @@ public: protected: void taskMain(void) { - LockedFile *lockedFile = NULL; + QScopedPointer lockedFile; unsigned int version = m_toolVersion; - QFileInfo toolFileInfo(m_toolName); - const QString toolShortName = QString("%1.%2").arg(toolFileInfo.baseName().toLower(), toolFileInfo.suffix().toLower()); + const QFileInfo toolFileInfo(m_toolName); + const QString toolShrtName = QString("%1.%2").arg(toolFileInfo.baseName().toLower(), toolFileInfo.suffix().toLower()); - QFileInfo customTool(QString("%1/tools/%2/%3").arg(m_appDir.canonicalPath(), QString::number(lamexp_version_build()), toolShortName)); - if(customTool.exists() && customTool.isFile()) + //Try to load a "custom" tool first + if(ENABLE_CUSTOM_TOOLS) { - qDebug("Setting up file: %s <- %s", toolShortName.toLatin1().constData(), m_appDir.relativeFilePath(customTool.canonicalFilePath()).toLatin1().constData()); - lockedFile = new LockedFile(customTool.canonicalFilePath()); version = UINT_MAX; s_bCustom = true; - } - else - { - qDebug("Extracting file: %s -> %s", m_toolName.toLatin1().constData(), toolShortName.toLatin1().constData()); - lockedFile = new LockedFile(m_toolResource.data(), QString("%1/lxp_%2").arg(MUtils::temp_folder(), toolShortName), m_toolHash); + const QFileInfo customTool(QString("%1/tools/%2/%3").arg(m_appDir.canonicalPath(), QString::number(lamexp_version_build()), toolShrtName)); + if(customTool.exists() && customTool.isFile()) + { + qDebug("Setting up file: %s <- %s", toolShrtName.toLatin1().constData(), m_appDir.relativeFilePath(customTool.canonicalFilePath()).toLatin1().constData()); + try + { + lockedFile.reset(new LockedFile(customTool.canonicalFilePath())); + version = UINT_MAX; s_bCustom = true; + } + catch(std::runtime_error&) + { + lockedFile.reset(); + } + } } - if(lockedFile) + //Try to load the tool from the "cache" next + if(lockedFile.isNull()) { - lamexp_tools_register(toolShortName, lockedFile, version, m_toolTag); + const QFileInfo chachedTool(QString("%1/cache/%2").arg(m_appDir.canonicalPath(), toolFileInfo.fileName())); + if(chachedTool.exists() && chachedTool.isFile()) + { + qDebug("Validating file: %s <- %s", toolShrtName.toLatin1().constData(), m_appDir.relativeFilePath(chachedTool.canonicalFilePath()).toLatin1().constData()); + try + { + lockedFile.reset(new LockedFile(chachedTool.canonicalFilePath(), m_toolHash)); + } + catch(std::runtime_error&) + { + lockedFile.reset(); + } + } } + + //If still not initialized, extract tool now! + if(lockedFile.isNull()) + { + qDebug("Extracting file: %s -> %s", m_toolName.toLatin1().constData(), toolShrtName.toLatin1().constData()); + lockedFile.reset(new LockedFile(m_toolResource.data(), QString("%1/lxp_%2").arg(MUtils::temp_folder(), toolShrtName), m_toolHash)); + } + + //Register tool + lamexp_tools_register(toolShrtName, lockedFile.take(), version, m_toolTag); } private: @@ -379,7 +413,7 @@ double InitializationThread::doInit(const size_t threadCount) pool->setMaxThreadCount((threadCount > 0) ? threadCount : qBound(2U, cores2threads(m_cpuFeatures.count), EXPECTED_TOOL_COUNT)); /* qWarning("Using %u threads for extraction.", pool->maxThreadCount()); */ - LockedFile::selfTest(); + FileHash::selfTest(); ExtractorTask::clearFlags(); //Start the timer @@ -697,7 +731,7 @@ void InitializationThread::selfTest(void) { const unsigned int cpu[4] = {CPU_TYPE_X86_GEN, CPU_TYPE_X86_SSE, CPU_TYPE_X64_GEN, CPU_TYPE_X64_SSE}; - LockedFile::selfTest(); + FileHash::selfTest(); for(size_t k = 0; k < 4; k++) { @@ -730,7 +764,7 @@ void InitializationThread::selfTest(void) qFatal("The resource for \"%s\" could not be opened!", MUTILS_UTF8(toolName)); break; } - QByteArray hash = LockedFile::fileHash(resource); + QByteArray hash = FileHash::computeHash(resource); if(hash.isNull() || _stricmp(hash.constData(), expectedHash.constData())) { qFatal("Hash check for tool \"%s\" has failed!", MUTILS_UTF8(toolName));