[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
|
||||
{
|
||||
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_db(db)
|
||||
, m_downloader(downloader)
|
||||
, m_tempDir(tempDir)
|
||||
{}
|
||||
|
||||
public:
|
||||
@ -35,4 +36,5 @@ private:
|
||||
std::string m_appBaseDir;
|
||||
IModuleDatabase & m_db;
|
||||
IDownloader& m_downloader;
|
||||
std::string m_tempDir;
|
||||
};
|
||||
|
||||
@ -177,6 +177,7 @@
|
||||
<ClInclude Include="api\SystemParamsProvider.h" />
|
||||
<ClInclude Include="api\SystemParamsProvider_win.h" />
|
||||
<ClInclude Include="src\HashUtils.h" />
|
||||
<ClInclude Include="src\SafeFileUtils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\CachedDownloader.cpp" />
|
||||
@ -188,6 +189,7 @@
|
||||
<ClCompile Include="src\LicenseClient.cpp" />
|
||||
<ClCompile Include="src\ModuleManager.cpp" />
|
||||
<ClCompile Include="src\ModuleUpdate.cpp" />
|
||||
<ClCompile Include="src\SafeFileUtils.cpp" />
|
||||
<ClCompile Include="src\SystemParams.cpp" />
|
||||
<ClCompile Include="src\SystemParamsProvider_win.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -60,6 +60,9 @@
|
||||
<ClInclude Include="api\IDownloader.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SafeFileUtils.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\HashUtils.cpp">
|
||||
@ -95,5 +98,8 @@
|
||||
<ClCompile Include="src\CachedDownloader.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SafeFileUtils.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,6 +1,7 @@
|
||||
#include "ModuleManager.h"
|
||||
|
||||
#include "HashUtils.h"
|
||||
#include "SafeFileUtils.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -8,6 +9,8 @@
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
void ModuleManager::applyUpdate(const std::string & moduleId, const ModuleUpdate & update)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
// We should remove old files first before extracting new ones
|
||||
boost::filesystem::path basePath(m_appBaseDir);
|
||||
std::for_each(module.filePaths.begin(), module.filePaths.end(), [&basePath](const auto& filePath)
|
||||
fs::path basePath(m_appBaseDir);
|
||||
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();
|
||||
}
|
||||
@ -45,7 +48,7 @@ void ModuleManager::applyUpdate(Module & module, const ModuleUpdate & update)
|
||||
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);
|
||||
}
|
||||
@ -61,21 +64,21 @@ std::string zipErrorToStr(int err)
|
||||
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_stat sb;
|
||||
int err;
|
||||
boost::filesystem::path basePath(m_appBaseDir);
|
||||
fs::path basePath(m_appBaseDir);
|
||||
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");
|
||||
}
|
||||
@ -103,7 +106,7 @@ inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesyste
|
||||
auto outPathRel = basePathRel / sb.name;
|
||||
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");
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
|
||||
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;
|
||||
while (sum != sb.size) {
|
||||
@ -130,7 +134,7 @@ inline std::set<std::string> ModuleManager::extractUpdate(const boost::filesyste
|
||||
sum += len;
|
||||
}
|
||||
}
|
||||
boost::filesystem::last_write_time(outPath, sb.mtime);
|
||||
fs::last_write_time(file.path(), sb.mtime);
|
||||
extractedFiles.insert(outPathRel.string());
|
||||
|
||||
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