[impl] Allow to postpone file deletion if file is dll exe file that is still in use
This commit is contained in:
parent
d142df6366
commit
4e1edd2a33
@ -15,10 +15,11 @@
|
|||||||
class ModuleManager
|
class ModuleManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModuleManager(const std::string& appBaseDir, IModuleDatabase& db, IDownloader& downloader)
|
ModuleManager(const std::string& appBaseDir, IModuleDatabase& db, IDownloader& downloader, const std::string& tempDir)
|
||||||
: m_appBaseDir(appBaseDir)
|
: m_appBaseDir(appBaseDir)
|
||||||
, m_db(db)
|
, m_db(db)
|
||||||
, m_downloader(downloader)
|
, m_downloader(downloader)
|
||||||
|
, m_tempDir(tempDir)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -35,4 +36,5 @@ private:
|
|||||||
std::string m_appBaseDir;
|
std::string m_appBaseDir;
|
||||||
IModuleDatabase & m_db;
|
IModuleDatabase & m_db;
|
||||||
IDownloader& m_downloader;
|
IDownloader& m_downloader;
|
||||||
|
std::string m_tempDir;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -177,6 +177,7 @@
|
|||||||
<ClInclude Include="api\SystemParamsProvider.h" />
|
<ClInclude Include="api\SystemParamsProvider.h" />
|
||||||
<ClInclude Include="api\SystemParamsProvider_win.h" />
|
<ClInclude Include="api\SystemParamsProvider_win.h" />
|
||||||
<ClInclude Include="src\HashUtils.h" />
|
<ClInclude Include="src\HashUtils.h" />
|
||||||
|
<ClInclude Include="src\SafeFileUtils.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\CachedDownloader.cpp" />
|
<ClCompile Include="src\CachedDownloader.cpp" />
|
||||||
@ -188,6 +189,7 @@
|
|||||||
<ClCompile Include="src\LicenseClient.cpp" />
|
<ClCompile Include="src\LicenseClient.cpp" />
|
||||||
<ClCompile Include="src\ModuleManager.cpp" />
|
<ClCompile Include="src\ModuleManager.cpp" />
|
||||||
<ClCompile Include="src\ModuleUpdate.cpp" />
|
<ClCompile Include="src\ModuleUpdate.cpp" />
|
||||||
|
<ClCompile Include="src\SafeFileUtils.cpp" />
|
||||||
<ClCompile Include="src\SystemParams.cpp" />
|
<ClCompile Include="src\SystemParams.cpp" />
|
||||||
<ClCompile Include="src\SystemParamsProvider_win.cpp" />
|
<ClCompile Include="src\SystemParamsProvider_win.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@ -60,6 +60,9 @@
|
|||||||
<ClInclude Include="api\IDownloader.h">
|
<ClInclude Include="api\IDownloader.h">
|
||||||
<Filter>api</Filter>
|
<Filter>api</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SafeFileUtils.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\HashUtils.cpp">
|
<ClCompile Include="src\HashUtils.cpp">
|
||||||
@ -95,5 +98,8 @@
|
|||||||
<ClCompile Include="src\CachedDownloader.cpp">
|
<ClCompile Include="src\CachedDownloader.cpp">
|
||||||
<Filter>src</Filter>
|
<Filter>src</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SafeFileUtils.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#include "ModuleManager.h"
|
#include "ModuleManager.h"
|
||||||
|
|
||||||
#include "HashUtils.h"
|
#include "HashUtils.h"
|
||||||
|
#include "SafeFileUtils.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@ -8,6 +9,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
void ModuleManager::applyUpdate(const std::string & moduleId, const ModuleUpdate & update)
|
void ModuleManager::applyUpdate(const std::string & moduleId, const ModuleUpdate & update)
|
||||||
{
|
{
|
||||||
auto module = m_db.findModule(moduleId).value_or(Module{ moduleId, -1 , {} });
|
auto module = m_db.findModule(moduleId).value_or(Module{ moduleId, -1 , {} });
|
||||||
@ -30,10 +33,10 @@ void ModuleManager::applyUpdate(Module & module, const ModuleUpdate & update)
|
|||||||
if (!(update.flag & static_cast<uint32_t>(ModuleUpdateFlags::incremental)))
|
if (!(update.flag & static_cast<uint32_t>(ModuleUpdateFlags::incremental)))
|
||||||
{
|
{
|
||||||
// We should remove old files first before extracting new ones
|
// We should remove old files first before extracting new ones
|
||||||
boost::filesystem::path basePath(m_appBaseDir);
|
fs::path basePath(m_appBaseDir);
|
||||||
std::for_each(module.filePaths.begin(), module.filePaths.end(), [&basePath](const auto& filePath)
|
std::for_each(module.filePaths.begin(), module.filePaths.end(), [&basePath, this](const auto& filePath)
|
||||||
{
|
{
|
||||||
boost::filesystem::remove(basePath / filePath);
|
safeRemoveFile(basePath / filePath, m_tempDir);
|
||||||
});
|
});
|
||||||
module.filePaths.clear();
|
module.filePaths.clear();
|
||||||
}
|
}
|
||||||
@ -45,7 +48,7 @@ void ModuleManager::applyUpdate(Module & module, const ModuleUpdate & update)
|
|||||||
module.filePaths.insert(filePaths.begin(), filePaths.end());
|
module.filePaths.insert(filePaths.begin(), filePaths.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::path ModuleManager::retrieveUpdate(const std::string & updateUrl)
|
fs::path ModuleManager::retrieveUpdate(const std::string & updateUrl)
|
||||||
{
|
{
|
||||||
return m_downloader.download(updateUrl);
|
return m_downloader.download(updateUrl);
|
||||||
}
|
}
|
||||||
@ -61,21 +64,21 @@ std::string zipErrorToStr(int err)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesystem::path& archivePath, const std::string & targetPath)
|
std::set<std::string> ModuleManager::extractUpdate(const fs::path& archivePath, const std::string & targetPath)
|
||||||
{
|
{
|
||||||
struct zip_file *zf = nullptr;
|
struct zip_file *zf = nullptr;
|
||||||
struct zip_stat sb;
|
struct zip_stat sb;
|
||||||
int err;
|
int err;
|
||||||
boost::filesystem::path basePath(m_appBaseDir);
|
fs::path basePath(m_appBaseDir);
|
||||||
basePath /= targetPath;
|
basePath /= targetPath;
|
||||||
boost::filesystem::path basePathRel(targetPath);
|
fs::path basePathRel(targetPath);
|
||||||
|
|
||||||
if (!boost::filesystem::exists(basePath))
|
if (!fs::exists(basePath))
|
||||||
{
|
{
|
||||||
boost::filesystem::create_directories(basePath);
|
fs::create_directories(basePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!boost::filesystem::is_directory(basePath))
|
if (!fs::is_directory(basePath))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Target path is not a directory");
|
throw std::runtime_error("Target path is not a directory");
|
||||||
}
|
}
|
||||||
@ -103,7 +106,7 @@ inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesyste
|
|||||||
auto outPathRel = basePathRel / sb.name;
|
auto outPathRel = basePathRel / sb.name;
|
||||||
if (sb.name[len - 1] == '/')
|
if (sb.name[len - 1] == '/')
|
||||||
{
|
{
|
||||||
if (!boost::filesystem::is_directory(outPath) && !boost::filesystem::create_directory(outPath))
|
if (!fs::is_directory(outPath) && !fs::create_directory(outPath))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Directory can't be extracted");
|
throw std::runtime_error("Directory can't be extracted");
|
||||||
}
|
}
|
||||||
@ -116,8 +119,9 @@ inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesyste
|
|||||||
throw std::runtime_error("Can't open file from the archive");
|
throw std::runtime_error("Can't open file from the archive");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto file = safeCreateFile(outPath, m_tempDir);
|
||||||
{
|
{
|
||||||
std::ofstream os(outPath.string(), std::ofstream::binary);
|
std::ofstream os = std::ofstream(file.path().native(), std::ofstream::binary);
|
||||||
|
|
||||||
uint64_t sum = 0;
|
uint64_t sum = 0;
|
||||||
while (sum != sb.size) {
|
while (sum != sb.size) {
|
||||||
@ -130,7 +134,7 @@ inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesyste
|
|||||||
sum += len;
|
sum += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::filesystem::last_write_time(outPath, sb.mtime);
|
fs::last_write_time(file.path(), sb.mtime);
|
||||||
extractedFiles.insert(outPathRel.string());
|
extractedFiles.insert(outPathRel.string());
|
||||||
|
|
||||||
zip_fclose(zf);
|
zip_fclose(zf);
|
||||||
|
|||||||
46
src/SafeFileUtils.cpp
Normal file
46
src/SafeFileUtils.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "SafeFileUtils.h"
|
||||||
|
#include <winerror.h>
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
void safeRemoveFile(const fs::path& p, const fs::path& tempFolder)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool result = fs::remove(p);
|
||||||
|
}
|
||||||
|
catch (fs::filesystem_error& e)
|
||||||
|
{
|
||||||
|
if (e.code().category() == boost::system::system_category()
|
||||||
|
&& e.code().value() == ERROR_ACCESS_DENIED)
|
||||||
|
{
|
||||||
|
auto cleanupFolder = tempFolder;
|
||||||
|
|
||||||
|
if (!fs::exists(cleanupFolder))
|
||||||
|
{
|
||||||
|
fs::create_directories(cleanupFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs::is_directory(cleanupFolder))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(".upd/.remove folder is not directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fileName = fs::unique_path();
|
||||||
|
fs::rename(p, cleanupFolder / fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeFile safeCreateFile(const fs::path & p, const fs::path& tempFolder)
|
||||||
|
{
|
||||||
|
if (fs::exists(p))
|
||||||
|
{
|
||||||
|
safeRemoveFile(p, tempFolder);
|
||||||
|
}
|
||||||
|
return SafeFile(p);
|
||||||
|
}
|
||||||
21
src/SafeFileUtils.h
Normal file
21
src/SafeFileUtils.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
void safeRemoveFile(const boost::filesystem::path& p, const boost::filesystem::path& tempFolder);
|
||||||
|
|
||||||
|
class SafeFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SafeFile(const boost::filesystem::path& p)
|
||||||
|
: m_path(p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const boost::filesystem::path& path() { return m_path; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::filesystem::path m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
SafeFile safeCreateFile(const boost::filesystem::path& p, const boost::filesystem::path& tempFolder);
|
||||||
Loading…
Reference in New Issue
Block a user