ZipHelpers: Load libzip on-demand

pull/3794/head
Stenzek 2 weeks ago
parent 3ccc0c45f4
commit 17a721c8f7
No known key found for this signature in database

@ -43,6 +43,7 @@ declare -a MANUAL_LIBS=(
"libwebpmux.so.3"
"libwebp.so.7"
"libz.so.1"
"libzip.so.5"
"libdiscord-rpc.so"
"libplutosvg.so.0"

@ -13,6 +13,7 @@
#include "host.h"
#include "system.h"
#include "util/dyn_libzip.h"
#include "util/imgui_manager.h"
#include "util/translation.h"
#include "util/zip_helpers.h"
@ -104,12 +105,13 @@ private:
class CheatArchive
{
public:
#if defined(_DEBUG) || defined(_DEVEL)
~CheatArchive()
{
// zip has to be destroyed before data
m_zip.reset();
m_data.deallocate();
DebugAssert(!m_zip);
DebugAssert(m_data.empty());
}
#endif
ALWAYS_INLINE bool IsOpen() const { return static_cast<bool>(m_zip); }
@ -133,8 +135,8 @@ public:
}
m_data = std::move(data.value());
m_zip = ZipHelpers::OpenManagedZipBuffer(m_data.data(), m_data.size(), 0, false, &error);
if (!m_zip) [[unlikely]]
if (!g_dyn_libzip.Open(&error) ||
!(m_zip = ZipHelpers::OpenManagedZipBuffer(m_data.data(), m_data.size(), 0, false, &error))) [[unlikely]]
{
ERROR_LOG("Failed to open cheat archive {}: {}", name, error.GetDescription());
return false;
@ -152,6 +154,13 @@ public:
return ret;
}
void Close()
{
// zip has to be destroyed before data
m_zip.reset();
m_data.deallocate();
}
private:
// Maybe counter-intuitive, but it ends up faster for reading a single game's cheats if we keep a
// copy of the archive in memory, as opposed to reading from disk.
@ -465,6 +474,13 @@ void Cheats::EnumerateChtFiles(const std::string_view serial, std::optional<Game
}
}
void Cheats::UnloadDatabase()
{
const std::unique_lock lock(s_archive_locals.zip_mutex);
s_archive_locals.cheats_zip.Close();
s_archive_locals.patches_zip.Close();
}
std::string_view Cheats::CodeInfo::GetNamePart() const
{
const std::string::size_type pos = name.rfind('\\');

@ -183,6 +183,9 @@ u32 GetActiveCheatCount();
/// Returns true if the widescreen patch is active.
bool IsWidescreenPatchActive();
/// Unloads the cheat database from memory.
void UnloadDatabase();
// Config sections/keys to use to enable patches.
extern const char* PATCHES_CONFIG_SECTION;
extern const char* CHEATS_CONFIG_SECTION;

@ -2,6 +2,7 @@
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#include "core.h"
#include "cheats.h"
#include "achievements.h"
#include "achievements_private.h"
#include "core_private.h"
@ -758,6 +759,8 @@ void Core::CoreThreadShutdown()
Achievements::Shutdown();
Cheats::UnloadDatabase();
GPUDevice::UnloadDynamicLibraries();
InputManager::CloseSources();

@ -28,11 +28,14 @@ add_library(util
core_audio_stream.h
cue_parser.cpp
cue_parser.h
dyn_shaderc.h
dyn_spirv_cross.h
dyn_libjpeg.h
dyn_libpng.h
dyn_libs.cpp
dyn_libwebp.h
dyn_libzip.h
dyn_sdl.h
dyn_shaderc.h
dyn_spirv_cross.h
dyn_sqlite.h
elf_file.cpp
elf_file.h
@ -106,11 +109,10 @@ target_include_directories(util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
get_target_property(JPEG_INCLUDE_DIRS libjpeg-turbo::jpeg INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(PNG_INCLUDE_DIRS PNG::png_shared INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(WEBP_INCLUDE_DIRS WebP::webp INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(util PRIVATE ${JPEG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${WEBP_INCLUDE_DIRS})
get_target_property(LIBZIP_INCLUDE_DIRS libzip::zip INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(util PRIVATE ${JPEG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${WEBP_INCLUDE_DIRS} ${LIBZIP_INCLUDE_DIRS})
target_link_libraries(util PUBLIC common imgui)
target_link_libraries(util PRIVATE libchdr lzma
plutosvg::plutosvg ZLIB::ZLIB SoundTouch::SoundTouchDLL xxhash
libzip::zip zstd::libzstd_shared reshadefx)
target_link_libraries(util PRIVATE libchdr lzma ZLIB::ZLIB SoundTouch::SoundTouchDLL xxhash zstd::libzstd_shared reshadefx)
if(ENABLE_X11)
target_sources(util PRIVATE
@ -291,6 +293,6 @@ function(add_util_resources target)
# Copy dynamically-loaded libraries into the bundle.
add_runtime_libraries(${target} spirv-cross-c-shared Shaderc::shaderc_shared SQLite3::sqlite3-shared SDL3::SDL3
freetype harfbuzz::harfbuzz plutosvg::plutosvg libjpeg-turbo::jpeg PNG::png_shared WebP::webp
WebP::sharpyuv WebP::webpdecoder WebP::webpdemux WebP::libwebpmux)
freetype harfbuzz::harfbuzz plutosvg::plutosvg libjpeg-turbo::jpeg PNG::png_shared libzip::zip
WebP::webp WebP::sharpyuv WebP::webpdecoder WebP::webpdemux WebP::libwebpmux)
endfunction()

@ -5,6 +5,7 @@
#include "dyn_libjpeg.h"
#include "dyn_libpng.h"
#include "dyn_libwebp.h"
#include "dyn_libzip.h"
#include "dyn_plutosvg.h"
#include "dyn_sdl.h"
#include "dyn_shaderc.h"
@ -26,6 +27,7 @@ static_assert(std::is_trivially_copyable_v<DynPlutoSvg> && std::is_standard_layo
static_assert(std::is_trivially_copyable_v<DynLibPNG> && std::is_standard_layout_v<DynLibPNG>);
static_assert(std::is_trivially_copyable_v<DynLibJPEG> && std::is_standard_layout_v<DynLibJPEG>);
static_assert(std::is_trivially_copyable_v<DynLibWebP> && std::is_standard_layout_v<DynLibWebP>);
static_assert(std::is_trivially_copyable_v<DynLibZip> && std::is_standard_layout_v<DynLibZip>);
static_assert(std::is_trivially_copyable_v<DynSDL> && std::is_standard_layout_v<DynSDL>);
static_assert(std::is_trivially_copyable_v<DynShaderc> && std::is_standard_layout_v<DynShaderc>);
static_assert(std::is_trivially_copyable_v<DynSpirvCross> && std::is_standard_layout_v<DynSpirvCross>);
@ -39,6 +41,7 @@ static constexpr int LIBPNG_MAJOR_VERSION = -1;
static constexpr int LIBJPEG_MAJOR_VERSION = -1;
static constexpr int LIBWEBP_MAJOR_VERSION = -1;
static constexpr int LIBSDL_MAJOR_VERSION = -1;
static constexpr int LIBZIP_MAJOR_VERSION = -1;
static constexpr int SQLITE_MAJOR_VERSION = -1;
static constexpr int SPIRV_CROSS_MAJOR_VERSION = -1;
#else
@ -47,6 +50,7 @@ static constexpr int PLUTOSVG_MAJOR_VERSION = 0;
static constexpr int LIBPNG_MAJOR_VERSION = 16;
static constexpr int LIBJPEG_MAJOR_VERSION = 62;
static constexpr int LIBWEBP_MAJOR_VERSION = 7;
static constexpr int LIBZIP_MAJOR_VERSION = 5;
static constexpr int LIBSDL_MAJOR_VERSION = 0;
static constexpr int SQLITE_MAJOR_VERSION = 3;
static constexpr int SPIRV_CROSS_MAJOR_VERSION = SPVC_C_API_VERSION_MAJOR;
@ -65,6 +69,8 @@ struct Locals
std::once_flag libpng_init_flag;
DynamicLibrary libwebp_library;
std::once_flag libwebp_init_flag;
DynamicLibrary libzip_library;
std::once_flag libzip_init_flag;
DynamicLibrary sdl_library;
std::once_flag sdl_init_flag;
DynamicLibrary sqlite_library;
@ -86,6 +92,7 @@ DynPlutoSvg g_dyn_plutosvg;
DynLibJPEG g_dyn_libjpeg;
DynLibWebP g_dyn_libwebp;
DynLibPNG g_dyn_libpng;
DynLibZip g_dyn_libzip;
DynSDL g_dyn_sdl;
DynSqlite g_dyn_sqlite;
DynShaderc g_dyn_shaderc;
@ -203,6 +210,21 @@ bool DynLibWebP::Open(Error* const error)
s_libwebp_symbols, error);
}
static const DynamicLibrary::SymbolTable s_libzip_symbols[] = {
#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_libzip.F},
DYN_LIBZIP_FUNCTIONS(RESOLVE_SYMBOL)
#undef RESOLVE_SYMBOL
};
bool DynLibZip::Open(Error* const error)
{
if (s_locals.libzip_library.IsOpen()) [[likely]]
return true;
return LoadDynLib("zip", LIBZIP_MAJOR_VERSION, s_locals.libzip_library, s_locals.libzip_init_flag, s_libzip_symbols,
error);
}
static const DynamicLibrary::SymbolTable s_sdl_symbols[] = {
#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_sdl.F},
DYN_SDL_FUNCTIONS(RESOLVE_SYMBOL)

@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#pragma once
#include <zip.h>
class Error;
#define DYN_LIBZIP_FUNCTIONS(X) \
X(zip_get_error) \
X(zip_error_set) \
X(zip_error_strerror) \
X(zip_error_fini) \
X(zip_open_from_source) \
X(zip_source_file_create) \
X(zip_source_function_create) \
X(zip_source_buffer_create) \
X(zip_source_free) \
X(zip_close) \
X(zip_discard) \
X(zip_get_num_entries) \
X(zip_get_name) \
X(zip_name_locate) \
X(zip_stat) \
X(zip_stat_index) \
X(zip_fopen) \
X(zip_fopen_index) \
X(zip_fread) \
X(zip_fclose)
struct DynLibZip
{
#define ADD_FUNC(F) decltype(&::F) F;
DYN_LIBZIP_FUNCTIONS(ADD_FUNC)
#undef ADD_FUNC
bool Open(Error* error);
};
extern DynLibZip g_dyn_libzip;

@ -25,7 +25,7 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DepsIncludeDir)spirv_cross</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);soundtouch.lib;zip.lib;zlib.lib;zstd.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);soundtouch.lib;zlib.lib;zstd.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

@ -5,6 +5,7 @@
<ClInclude Include="animated_image.h" />
<ClInclude Include="dyn_libjpeg.h" />
<ClInclude Include="dyn_libwebp.h" />
<ClInclude Include="dyn_libzip.h" />
<ClInclude Include="dyn_sdl.h" />
<ClInclude Include="dyn_sqlite.h" />
<ClInclude Include="http_cache.h" />

@ -89,6 +89,7 @@
<ClInclude Include="dyn_sdl.h" />
<ClInclude Include="dyn_libjpeg.h" />
<ClInclude Include="dyn_libwebp.h" />
<ClInclude Include="dyn_libzip.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="state_wrapper.cpp" />

@ -2,6 +2,7 @@
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#include "zip_helpers.h"
#include "dyn_libzip.h"
#include "common/error.h"
#include "common/file_system.h"
@ -9,7 +10,6 @@
#include "common/progress_callback.h"
#include <fmt/format.h>
#include <zip.h>
LOG_CHANNEL(Ungrouped);
@ -18,7 +18,7 @@ void ZipHelpers::ZipFileDeleter::operator()(zip_file_t* zf)
if (!zf)
return;
zip_fclose(zf);
g_dyn_libzip.zip_fclose(zf);
}
void ZipHelpers::ZipDeleter::operator()(zip_t* zf)
@ -26,25 +26,25 @@ void ZipHelpers::ZipDeleter::operator()(zip_t* zf)
if (!zf)
return;
const int err = zip_close(zf);
const int err = g_dyn_libzip.zip_close(zf);
if (err != 0)
{
ERROR_LOG("Failed to close zip file: {}", err);
zip_discard(zf);
g_dyn_libzip.zip_discard(zf);
}
}
void ZipHelpers::SetErrorObject(Error* error, std::string_view msg, zip_error_t* ze, bool finalize /*= true*/)
{
Error::SetStringFmt(error, "{}{}", msg, ze ? zip_error_strerror(ze) : "UNKNOWN");
Error::SetStringFmt(error, "{}{}", msg, ze ? g_dyn_libzip.zip_error_strerror(ze) : "UNKNOWN");
if (finalize && ze)
zip_error_fini(ze);
g_dyn_libzip.zip_error_fini(ze);
}
ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipFile(const char* filename, int flags, Error* error /*= nullptr*/)
{
zip_error_t ze;
zip_source_t* zs = zip_source_file_create(filename, 0, 0, &ze);
zip_source_t* zs = g_dyn_libzip.zip_source_file_create(filename, 0, 0, &ze);
zip_t* zip;
if (!zs)
{
@ -53,11 +53,11 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipFile(const char* filename, int
}
else
{
if (!(zip = zip_open_from_source(zs, flags, &ze)))
if (!(zip = g_dyn_libzip.zip_open_from_source(zs, flags, &ze)))
{
// have to clean up source
SetErrorObject(error, "zip_open_from_source() failed: {}", &ze);
zip_source_free(zs);
g_dyn_libzip.zip_source_free(zs);
}
}
@ -67,6 +67,9 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipFile(const char* filename, int
namespace ZipHelpers {
static zip_int64_t CFileSourceCallback(void* userdata, void* data, zip_uint64_t len, zip_source_cmd_t cmd)
{
#define LOCAL_ZIP_SOURCE_GET_ARGS(type, data, len, error) \
((len) < sizeof(type) ? g_dyn_libzip.zip_error_set((error), ZIP_ER_INVAL, 0), (type*)NULL : (type*)(data))
std::FILE* fp = static_cast<std::FILE*>(userdata);
switch (cmd)
{
@ -90,7 +93,7 @@ static zip_int64_t CFileSourceCallback(void* userdata, void* data, zip_uint64_t
case ZIP_SOURCE_STAT:
{
FILESYSTEM_STAT_DATA st;
zip_stat_t* zst = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, len, nullptr);
zip_stat_t* zst = LOCAL_ZIP_SOURCE_GET_ARGS(zip_stat_t, data, len, nullptr);
if (!zst || !FileSystem::StatFile(fp, &st))
return -1;
@ -102,7 +105,7 @@ static zip_int64_t CFileSourceCallback(void* userdata, void* data, zip_uint64_t
case ZIP_SOURCE_SEEK:
{
const zip_source_args_seek_t* args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, nullptr);
const zip_source_args_seek_t* args = LOCAL_ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, nullptr);
if (!args)
return -1;
@ -128,6 +131,8 @@ static zip_int64_t CFileSourceCallback(void* userdata, void* data, zip_uint64_t
default:
return -1;
}
#undef LOCAL_ZIP_SOURCE_GET_ARGS
}
} // namespace ZipHelpers
@ -135,7 +140,7 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipCFile(std::FILE* fp, int flags
{
zip_error_t ze;
zip_t* zip;
zip_source_t* zs = zip_source_function_create(&CFileSourceCallback, fp, &ze);
zip_source_t* zs = g_dyn_libzip.zip_source_function_create(&CFileSourceCallback, fp, &ze);
if (!zs)
{
SetErrorObject(error, "zip_source_filep_create() failed: ", &ze);
@ -144,11 +149,11 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipCFile(std::FILE* fp, int flags
}
else
{
if (!(zip = zip_open_from_source(zs, flags, &ze)))
if (!(zip = g_dyn_libzip.zip_open_from_source(zs, flags, &ze)))
{
// have to clean up source
SetErrorObject(error, "zip_open_from_source() failed: {}", &ze);
zip_source_free(zs);
g_dyn_libzip.zip_source_free(zs);
}
}
return ManagedZipT(zip);
@ -158,7 +163,7 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipBuffer(const void* buffer, siz
Error* error /*= nullptr*/)
{
zip_error_t ze;
zip_source_t* zs = zip_source_buffer_create(buffer, size, free_buffer, &ze);
zip_source_t* zs = g_dyn_libzip.zip_source_buffer_create(buffer, size, free_buffer, &ze);
zip_t* zip;
if (!zs)
{
@ -169,11 +174,11 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipBuffer(const void* buffer, siz
}
else
{
if (!(zip = zip_open_from_source(zs, flags, &ze)))
if (!(zip = g_dyn_libzip.zip_open_from_source(zs, flags, &ze)))
{
// have to clean up source
SetErrorObject(error, "zip_open_from_source() failed: {}", &ze);
zip_source_free(zs);
g_dyn_libzip.zip_source_free(zs);
}
}
@ -183,7 +188,7 @@ ZipHelpers::ManagedZipT ZipHelpers::OpenManagedZipBuffer(const void* buffer, siz
std::vector<std::string> ZipHelpers::ReadFileListInZip(zip_t* zip)
{
std::vector<std::string> ret;
zip_int64_t num_entries = zip_get_num_entries(zip, 0);
zip_int64_t num_entries = g_dyn_libzip.zip_get_num_entries(zip, 0);
if constexpr (sizeof(size_t) < sizeof(zip_int64_t))
num_entries = std::min(num_entries, static_cast<zip_int64_t>(std::numeric_limits<size_t>::max()));
if (num_entries <= 0)
@ -192,7 +197,7 @@ std::vector<std::string> ZipHelpers::ReadFileListInZip(zip_t* zip)
ret.reserve(static_cast<size_t>(num_entries));
for (zip_uint64_t i = 0; i < static_cast<zip_uint64_t>(num_entries); i++)
{
const char* name = zip_get_name(zip, i, ZIP_FL_ENC_GUESS);
const char* name = g_dyn_libzip.zip_get_name(zip, i, ZIP_FL_ENC_GUESS);
if (name)
ret.emplace_back(name);
}
@ -203,18 +208,18 @@ std::vector<std::string> ZipHelpers::ReadFileListInZip(zip_t* zip)
ZipHelpers::ManagedZipFileT ZipHelpers::OpenManagedFileInZip(zip_t* zip, const char* filename, u32 flags,
Error* error /*= nullptr*/)
{
zip_file_t* zf = zip_fopen(zip, filename, flags);
zip_file_t* zf = g_dyn_libzip.zip_fopen(zip, filename, flags);
if (!zf)
SetErrorObject(error, "zip_fopen() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_fopen() failed: ", g_dyn_libzip.zip_get_error(zip), false);
return ManagedZipFileT(zf);
}
ZipHelpers::ManagedZipFileT ZipHelpers::OpenManagedFileIndexInZip(zip_t* zip, u64 index, u32 flags,
Error* error /*= nullptr*/)
{
zip_file_t* zf = zip_fopen_index(zip, index, flags);
zip_file_t* zf = g_dyn_libzip.zip_fopen_index(zip, index, flags);
if (!zf)
SetErrorObject(error, "zip_fopen_index() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_fopen_index() failed: ", g_dyn_libzip.zip_get_error(zip), false);
return ManagedZipFileT(zf);
}
@ -222,9 +227,9 @@ std::optional<u64> ZipHelpers::GetFileSizeInZip(zip_t* zip, const char* name, bo
Error* error /*= nullptr*/)
{
zip_stat_t st;
if (zip_stat(zip, name, 0, &st) != 0)
if (g_dyn_libzip.zip_stat(zip, name, 0, &st) != 0)
{
SetErrorObject(error, "zip_stat() failed: ", zip_get_error(zip));
SetErrorObject(error, "zip_stat() failed: ", g_dyn_libzip.zip_get_error(zip));
return std::nullopt;
}
@ -269,17 +274,17 @@ bool ZipHelpers::ExtractFileToDisk(zip_t* zip, const char* name, std::FILE* fp,
{
const int flags = case_sensitive ? 0 : ZIP_FL_NOCASE;
const zip_int64_t file_index = zip_name_locate(zip, name, flags);
const zip_int64_t file_index = g_dyn_libzip.zip_name_locate(zip, name, flags);
if (file_index < 0)
{
SetErrorObject(error, "zip_name_locate() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_name_locate() failed: ", g_dyn_libzip.zip_get_error(zip), false);
return false;
}
zip_file_t* zf = zip_fopen_index(zip, file_index, flags);
zip_file_t* zf = g_dyn_libzip.zip_fopen_index(zip, file_index, flags);
if (!zf)
{
SetErrorObject(error, "zip_fopen_index() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_fopen_index() failed: ", g_dyn_libzip.zip_get_error(zip), false);
return false;
}
@ -289,7 +294,7 @@ bool ZipHelpers::ExtractFileToDisk(zip_t* zip, const char* name, std::FILE* fp,
{
zip_stat_t zst;
update_progress =
(zip_stat_index(zip, file_index, flags, &zst) == 0 && (zst.valid & ZIP_STAT_SIZE) && zst.size > 0);
(g_dyn_libzip.zip_stat_index(zip, file_index, flags, &zst) == 0 && (zst.valid & ZIP_STAT_SIZE) && zst.size > 0);
if (update_progress)
{
progress->PushState();
@ -299,12 +304,12 @@ bool ZipHelpers::ExtractFileToDisk(zip_t* zip, const char* name, std::FILE* fp,
for (;;)
{
const s64 read = zip_fread(zf, chunk_buffer.data(), chunk_size);
const s64 read = g_dyn_libzip.zip_fread(zf, chunk_buffer.data(), chunk_size);
if (read < 0)
{
// read error
SetErrorObject(error, "zip_fread() failed: ", zip_get_error(zip), false);
zip_fclose(zf);
SetErrorObject(error, "zip_fread() failed: ", g_dyn_libzip.zip_get_error(zip), false);
g_dyn_libzip.zip_fclose(zf);
if (update_progress)
progress->PopState();
@ -316,7 +321,7 @@ bool ZipHelpers::ExtractFileToDisk(zip_t* zip, const char* name, std::FILE* fp,
{
// write error
Error::SetErrno(error, "fwrite() failed: ", errno);
zip_fclose(zf);
g_dyn_libzip.zip_fclose(zf);
if (update_progress)
progress->PopState();
@ -335,7 +340,7 @@ bool ZipHelpers::ExtractFileToDisk(zip_t* zip, const char* name, std::FILE* fp,
if (update_progress)
progress->PopState();
zip_fclose(zf);
g_dyn_libzip.zip_fclose(zf);
if (std::fflush(fp) != 0)
{
@ -355,34 +360,34 @@ static std::optional<T> ReadFileInZipToContainer(zip_t* zip, const char* name, b
const int flags = case_sensitive ? 0 : ZIP_FL_NOCASE;
std::optional<T> ret;
const zip_int64_t file_index = zip_name_locate(zip, name, flags);
const zip_int64_t file_index = g_dyn_libzip.zip_name_locate(zip, name, flags);
if (file_index >= 0)
{
zip_stat_t zst;
if (zip_stat_index(zip, file_index, flags, &zst) == 0)
if (g_dyn_libzip.zip_stat_index(zip, file_index, flags, &zst) == 0)
{
zip_file_t* zf = zip_fopen_index(zip, file_index, flags);
zip_file_t* zf = g_dyn_libzip.zip_fopen_index(zip, file_index, flags);
if (zf)
{
ret = T();
ret->resize(static_cast<size_t>(zst.size));
if (zip_fread(zf, ret->data(), ret->size()) != static_cast<zip_int64_t>(ret->size()))
if (g_dyn_libzip.zip_fread(zf, ret->data(), ret->size()) != static_cast<zip_int64_t>(ret->size()))
{
SetErrorObject(error, "zip_fread() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_fread() failed: ", g_dyn_libzip.zip_get_error(zip), false);
ret.reset();
}
zip_fclose(zf);
g_dyn_libzip.zip_fclose(zf);
}
}
else
{
SetErrorObject(error, "zip_stat_index() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_stat_index() failed: ", g_dyn_libzip.zip_get_error(zip), false);
}
}
else
{
SetErrorObject(error, "zip_name_locate() failed: ", zip_get_error(zip), false);
SetErrorObject(error, "zip_name_locate() failed: ", g_dyn_libzip.zip_get_error(zip), false);
}
return ret;
@ -396,7 +401,7 @@ static std::optional<T> ReadFileInZipToContainer(zip_file_t* file, u32 chunk_siz
{
const size_t pos = ret->size();
ret->resize(pos + chunk_size);
const s64 read = zip_fread(file, ret->data() + pos, chunk_size);
const s64 read = g_dyn_libzip.zip_fread(file, ret->data() + pos, chunk_size);
if (read < 0)
{
// read error

Loading…
Cancel
Save