diff --git a/3rdparty/zlib/CMakeLists.txt b/3rdparty/zlib/CMakeLists.txt
index a92d05c13e..7f75b85fb9 100644
--- a/3rdparty/zlib/CMakeLists.txt
+++ b/3rdparty/zlib/CMakeLists.txt
@@ -5,6 +5,7 @@ if (USE_SYSTEM_ZLIB)
add_library(3rdparty_zlib INTERFACE)
target_link_libraries(3rdparty_zlib INTERFACE ${ZLIB_LIBRARIES})
target_include_directories(3rdparty_zlib INTERFACE ${ZLIB_INCLUDE_DIRS})
+ target_compile_definitions(3rdparty_zlib INTERFACE -DZLIB_CONST=1)
else()
message(STATUS "RPCS3: Using builtin ZLIB")
set(SKIP_INSTALL_ALL ON)
@@ -13,4 +14,5 @@ else()
add_library(3rdparty_zlib INTERFACE)
target_link_libraries(3rdparty_zlib INTERFACE zlibstatic)
target_include_directories(3rdparty_zlib INTERFACE zlib ${CMAKE_CURRENT_BINARY_DIR}/zlib)
+ target_compile_definitions(3rdparty_zlib INTERFACE -DZLIB_CONST=1)
endif()
diff --git a/3rdparty/zlib/zlib.vcxproj b/3rdparty/zlib/zlib.vcxproj
index 59c6f6127a..a333694e38 100644
--- a/3rdparty/zlib/zlib.vcxproj
+++ b/3rdparty/zlib/zlib.vcxproj
@@ -22,6 +22,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{60F89955-91C6-3A36-8000-13C592FEC2DF}
@@ -63,7 +80,7 @@
- WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ WIN32;ZLIB_CONST;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
$(WarningLevel)
ProgramDatabase
Disabled
@@ -90,7 +107,7 @@
true
$(DisableSpecificWarnings);4127;4131;4242;4244
$(TreatWarningAsError)
- WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ WIN32;ZLIB_CONST;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
true
diff --git a/Utilities/JIT.cpp b/Utilities/JIT.cpp
index 5d77d16f69..caec5a6b22 100644
--- a/Utilities/JIT.cpp
+++ b/Utilities/JIT.cpp
@@ -9,8 +9,8 @@
#include "util/asm.hpp"
#include "util/v128.hpp"
#include "util/simd.hpp"
+#include "Crypto/unzip.h"
#include
-#include
#ifdef __linux__
#define CAN_OVERCOMMIT
@@ -136,7 +136,7 @@ static atomic_t s_code_pos{0}, s_data_pos{0};
static std::vector s_code_init, s_data_init;
template & Ctr, uint Off, utils::protection Prot>
-static u8* add_jit_memory(usz size, uint align)
+static u8* add_jit_memory(usz size, usz align)
{
// Select subrange
u8* pointer = get_jit_memory() + Off;
@@ -251,7 +251,7 @@ uchar* jit_runtime::_alloc(usz size, usz align) noexcept
return jit_runtime::alloc(size, align, true);
}
-u8* jit_runtime::alloc(usz size, uint align, bool exec) noexcept
+u8* jit_runtime::alloc(usz size, usz align, bool exec) noexcept
{
if (exec)
{
@@ -1170,42 +1170,18 @@ public:
//fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize());
name.append(".gz");
- z_stream zs{};
- uLong zsz = compressBound(::narrow(obj.getBufferSize())) + 256;
- auto zbuf = std::make_unique(zsz);
-#ifndef _MSC_VER
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
- deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY);
-#ifndef _MSC_VER
-#pragma GCC diagnostic pop
-#endif
- zs.avail_in = static_cast(obj.getBufferSize());
- zs.next_in = reinterpret_cast(const_cast(obj.getBufferStart()));
- zs.avail_out = static_cast(zsz);
- zs.next_out = zbuf.get();
+ const std::vector zbuf = zip(reinterpret_cast(obj.getBufferStart()), obj.getBufferSize());
- switch (deflate(&zs, Z_FINISH))
- {
- case Z_OK:
- case Z_STREAM_END:
- {
- deflateEnd(&zs);
- break;
- }
- default:
+ if (zbuf.empty())
{
jit_log.error("LLVM: Failed to compress module: %s", _module->getName().data());
- deflateEnd(&zs);
return;
}
- }
- if (!fs::write_file(name, fs::rewrite, zbuf.get(), zsz - zs.avail_out))
+ if (!fs::write_file(name, fs::rewrite, zbuf.data(), zbuf.size()))
{
- jit_log.error("LLVM: Failed to create module file: %s (%s)", name, fs::g_tls_error);
- return;
+ jit_log.error("LLVM: Failed to create module file: %s (%s)", name, fs::g_tls_error);
+ return;
}
jit_log.notice("LLVM: Created module: %s", _module->getName().data());
@@ -1215,57 +1191,21 @@ public:
{
if (fs::file cached{path + ".gz", fs::read})
{
- std::vector gz = cached.to_vector();
- std::vector out;
- z_stream zs{};
+ const std::vector cached_data = cached.to_vector();
- if (gz.empty()) [[unlikely]]
+ if (cached_data.empty()) [[unlikely]]
{
return nullptr;
}
-#ifndef _MSC_VER
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
- inflateInit2(&zs, 16 + 15);
-#ifndef _MSC_VER
-#pragma GCC diagnostic pop
-#endif
- zs.avail_in = static_cast(gz.size());
- zs.next_in = gz.data();
- out.resize(gz.size() * 6);
- zs.avail_out = static_cast(out.size());
- zs.next_out = out.data();
- while (zs.avail_in)
+ const std::vector out = unzip(cached_data);
+
+ if (out.empty())
{
- switch (inflate(&zs, Z_FINISH))
- {
- case Z_OK: break;
- case Z_STREAM_END: break;
- case Z_BUF_ERROR:
- {
- if (zs.avail_in)
- break;
- [[fallthrough]];
- }
- default:
- inflateEnd(&zs);
- return nullptr;
- }
-
- if (zs.avail_in)
- {
- auto cur_size = zs.next_out - out.data();
- out.resize(out.size() + 65536);
- zs.avail_out = static_cast(out.size() - cur_size);
- zs.next_out = out.data() + cur_size;
- }
+ jit_log.error("LLVM: Failed to unzip module: '%s'", path);
+ return nullptr;
}
- out.resize(zs.next_out - out.data());
- inflateEnd(&zs);
-
auto buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(out.size());
std::memcpy(buf->getBufferStart(), out.data(), out.size());
return buf;
diff --git a/Utilities/JIT.h b/Utilities/JIT.h
index 498d5baf6b..60a9f155af 100644
--- a/Utilities/JIT.h
+++ b/Utilities/JIT.h
@@ -90,7 +90,7 @@ struct jit_runtime final : jit_runtime_base
uchar* _alloc(usz size, usz align) noexcept override;
// Allocate memory
- static u8* alloc(usz size, uint align, bool exec = true) noexcept;
+ static u8* alloc(usz size, usz align, bool exec = true) noexcept;
// Should be called at least once after global initialization
static void initialize();
diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp
index a553bca1bd..8e1b8e9bd4 100644
--- a/rpcs3/Crypto/unself.cpp
+++ b/rpcs3/Crypto/unself.cpp
@@ -5,9 +5,9 @@
#include "Emu/VFS.h"
#include "Emu/System.h"
#include "Emu/system_utils.hpp"
+#include "Crypto/unzip.h"
#include
-#include
inline u8 Read8(const fs::file& f)
{
@@ -767,72 +767,32 @@ std::vector SCEDecrypter::MakeFile()
u32 data_buf_offset = 0;
// Write data.
- for (unsigned int i = 0; i < meta_hdr.section_count; i++)
+ for (u32 i = 0; i < meta_hdr.section_count; i++)
{
+ const MetadataSectionHeader& hdr = meta_shdr[i];
+ const u8* src = data_buf.get() + data_buf_offset;
fs::file out_f = fs::make_stream>();
- bool isValid = true;
+ bool is_valid = true;
// Decompress if necessary.
- if (meta_shdr[i].compressed == 2)
+ if (hdr.compressed == 2)
{
- const usz BUFSIZE = 32 * 1024;
- u8 tempbuf[BUFSIZE];
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = ::narrow(meta_shdr[i].data_size);
- strm.avail_out = BUFSIZE;
- strm.next_in = data_buf.get()+data_buf_offset;
- strm.next_out = tempbuf;
-#ifndef _MSC_VER
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
- int ret = inflateInit(&strm);
-#ifndef _MSC_VER
-#pragma GCC diagnostic pop
-#endif
- while (strm.avail_in)
- {
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_END)
- break;
- if (ret != Z_OK)
- isValid = false;
-
- if (!strm.avail_out) {
- out_f.write(tempbuf, BUFSIZE);
- strm.next_out = tempbuf;
- strm.avail_out = BUFSIZE;
- }
- else
- break;
- }
-
- int inflate_res = Z_OK;
- inflate_res = inflate(&strm, Z_FINISH);
-
- if (inflate_res != Z_STREAM_END)
- isValid = false;
-
- out_f.write(tempbuf, BUFSIZE - strm.avail_out);
- inflateEnd(&strm);
+ is_valid = unzip(src, hdr.data_size, out_f);
}
else
{
// Write the data.
- out_f.write(data_buf.get()+data_buf_offset, meta_shdr[i].data_size);
+ out_f.write(src, hdr.data_size);
}
// Advance the data buffer offset by data size.
- data_buf_offset += ::narrow(meta_shdr[i].data_size);
+ data_buf_offset += ::narrow(hdr.data_size);
if (out_f.pos() != out_f.size())
fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size());
- if (isValid) vec.push_back(std::move(out_f));
+ if (is_valid) vec.push_back(std::move(out_f));
}
return vec;
diff --git a/rpcs3/Crypto/unzip.cpp b/rpcs3/Crypto/unzip.cpp
new file mode 100644
index 0000000000..f2d46f161a
--- /dev/null
+++ b/rpcs3/Crypto/unzip.cpp
@@ -0,0 +1,185 @@
+#include "stdafx.h"
+#include "unzip.h"
+
+#include
+
+std::vector unzip(const void* src, usz size)
+{
+ if (!src || !size) [[unlikely]]
+ {
+ return {};
+ }
+
+ std::vector out(size * 6);
+
+ z_stream zs{};
+#ifndef _MSC_VER
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+ int res = inflateInit2(&zs, 16 + 15);
+#ifndef _MSC_VER
+#pragma GCC diagnostic pop
+#endif
+ zs.avail_in = static_cast(size);
+ zs.next_in = reinterpret_cast(src);
+ zs.avail_out = static_cast(out.size());
+ zs.next_out = out.data();
+
+ while (zs.avail_in)
+ {
+ switch (inflate(&zs, Z_FINISH))
+ {
+ case Z_OK:
+ case Z_STREAM_END:
+ break;
+ case Z_BUF_ERROR:
+ if (zs.avail_in)
+ break;
+ [[fallthrough]];
+ default:
+ inflateEnd(&zs);
+ return out;
+ }
+
+ if (zs.avail_in)
+ {
+ const auto cur_size = zs.next_out - out.data();
+ out.resize(out.size() + 65536);
+ zs.avail_out = static_cast(out.size() - cur_size);
+ zs.next_out = &out[cur_size];
+ }
+ }
+
+ out.resize(zs.next_out - out.data());
+
+ res = inflateEnd(&zs);
+
+ return out;
+}
+
+bool unzip(const void* src, usz size, fs::file& out)
+{
+ if (!src || !size || !out)
+ {
+ return false;
+ }
+
+ bool is_valid = true;
+
+ constexpr usz BUFSIZE = 32ULL * 1024ULL;
+ std::vector tempbuf(BUFSIZE);
+ z_stream strm{};
+ strm.avail_in = ::narrow(size);
+ strm.avail_out = static_cast(tempbuf.size());
+ strm.next_in = reinterpret_cast(src);
+ strm.next_out = tempbuf.data();
+#ifndef _MSC_VER
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+ int res = inflateInit(&strm);
+#ifndef _MSC_VER
+#pragma GCC diagnostic pop
+#endif
+ while (strm.avail_in)
+ {
+ res = inflate(&strm, Z_NO_FLUSH);
+ if (res == Z_STREAM_END)
+ break;
+ if (res != Z_OK)
+ is_valid = false;
+
+ if (strm.avail_out)
+ break;
+
+ if (out.write(tempbuf.data(), tempbuf.size()) != tempbuf.size())
+ {
+ is_valid = false;
+ }
+
+ strm.next_out = tempbuf.data();
+ strm.avail_out = static_cast(tempbuf.size());
+ }
+
+ res = inflate(&strm, Z_FINISH);
+
+ if (res != Z_STREAM_END)
+ is_valid = false;
+
+ if (strm.avail_out < tempbuf.size())
+ {
+ const usz bytes_to_write = tempbuf.size() - strm.avail_out;
+
+ if (out.write(tempbuf.data(), bytes_to_write) != bytes_to_write)
+ {
+ is_valid = false;
+ }
+ }
+
+ res = inflateEnd(&strm);
+
+ return is_valid;
+}
+
+std::vector zip(const void* src, usz size)
+{
+ if (!src || !size)
+ {
+ return {};
+ }
+
+ const uLong zsz = compressBound(::narrow(size)) + 256;
+ std::vector out(zsz);
+
+ z_stream zs{};
+#ifndef _MSC_VER
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+ int res = deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY);
+#ifndef _MSC_VER
+#pragma GCC diagnostic pop
+#endif
+ zs.avail_in = static_cast(size);
+ zs.next_in = reinterpret_cast(src);
+ zs.avail_out = static_cast(out.size());
+ zs.next_out = out.data();
+
+ res = deflate(&zs, Z_FINISH);
+
+ switch (res)
+ {
+ case Z_OK:
+ case Z_STREAM_END:
+ if (zs.avail_out)
+ {
+ out.resize(zsz - zs.avail_out);
+ }
+ break;
+ default:
+ out.clear();
+ break;
+ }
+
+ deflateEnd(&zs);
+
+ return out;
+}
+
+bool zip(const void* src, usz size, fs::file& out)
+{
+ if (!src || !size || !out)
+ {
+ return false;
+ }
+
+ const std::vector zipped = zip(src, size);
+
+ if (zipped.empty() || out.write(zipped.data(), zipped.size()) != zipped.size())
+ {
+ return false;
+ }
+
+ return true;
+}
diff --git a/rpcs3/Crypto/unzip.h b/rpcs3/Crypto/unzip.h
new file mode 100644
index 0000000000..dc7701da3e
--- /dev/null
+++ b/rpcs3/Crypto/unzip.h
@@ -0,0 +1,33 @@
+#pragma once
+
+std::vector unzip(const void* src, usz size);
+
+template
+std::vector unzip(const T& src)
+{
+ return unzip(src.data(), src.size());
+}
+
+bool unzip(const void* src, usz size, fs::file& out);
+
+template
+bool unzip(const std::vector& src, fs::file& out)
+{
+ return unzip(src.data(), src.size(), out);
+}
+
+std::vector zip(const void* src, usz size);
+
+template
+std::vector zip(const T& src)
+{
+ return zip(src.data(), src.size());
+}
+
+bool zip(const void* src, usz size, fs::file& out);
+
+template
+bool zip(const T& src, fs::file& out)
+{
+ return zip(src.data(), src.size(), out);
+}
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index 70df0385bf..e29c119c88 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -116,6 +116,7 @@ target_sources(rpcs3_emu PRIVATE
../Crypto/unedat.cpp
../Crypto/unpkg.cpp
../Crypto/unself.cpp
+ ../Crypto/unzip.cpp
../Crypto/utils.cpp
)
diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj
index 5e7215434c..bcadb9051e 100644
--- a/rpcs3/emucore.vcxproj
+++ b/rpcs3/emucore.vcxproj
@@ -42,8 +42,8 @@
Use
..\3rdparty\miniupnp\miniupnp\miniupnpc\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\flatbuffers\include;..\3rdparty\libusb\libusb\libusb;..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\zlib\zlib;..\3rdparty\llvm\llvm\include;..\3rdparty\llvm\llvm\llvm\include;..\3rdparty\llvm\llvm_build\include;$(VULKAN_SDK)\Include
MaxSpeed
- MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;%(PreprocessorDefinitions)
- MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;%(PreprocessorDefinitions)
+ MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)
+ MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)
cmd.exe /c "$(SolutionDir)\Utilities\git-version-gen.cmd"
@@ -54,6 +54,7 @@
+
true
@@ -484,6 +485,7 @@
+
diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters
index ee1c8bb2ec..087b89c120 100644
--- a/rpcs3/emucore.vcxproj.filters
+++ b/rpcs3/emucore.vcxproj.filters
@@ -1171,6 +1171,9 @@
Emu\GPU\RSX\Core
+
+ Crypto
+
@@ -2383,6 +2386,9 @@
Emu\GPU\RSX\Core
+
+ Crypto
+
diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 0b9baabdcb..1df0ca2339 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -79,7 +79,7 @@
4577;4467;4281;%(DisableSpecificWarnings)
$(IntDir)
MaxSpeed
- _WINDOWS;UNICODE;WIN32;WIN64;WIN32_LEAN_AND_MEAN;HAVE_VULKAN;MINIUPNP_STATICLIB;HAVE_SDL2;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_SVG_LIB;%(PreprocessorDefinitions)
+ _WINDOWS;UNICODE;WIN32;WIN64;WIN32_LEAN_AND_MEAN;HAVE_VULKAN;MINIUPNP_STATICLIB;ZLIB_CONST;HAVE_SDL2;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_SVG_LIB;%(PreprocessorDefinitions)
false
$(IntDir)vc$(PlatformToolsetVersion).pdb
true
@@ -132,7 +132,7 @@
4577;4467;4281;%(DisableSpecificWarnings)
$(IntDir)
Disabled
- _WINDOWS;UNICODE;WIN32;WIN64;WIN32_LEAN_AND_MEAN;HAVE_VULKAN;MINIUPNP_STATICLIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_SVG_LIB;%(PreprocessorDefinitions)
+ _WINDOWS;UNICODE;WIN32;WIN64;WIN32_LEAN_AND_MEAN;HAVE_VULKAN;MINIUPNP_STATICLIB;ZLIB_CONST;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;QT_SVG_LIB;%(PreprocessorDefinitions)
false
true
true
diff --git a/rpcs3/rpcs3qt/log_viewer.cpp b/rpcs3/rpcs3qt/log_viewer.cpp
index d39bfd5367..8073bcee74 100644
--- a/rpcs3/rpcs3qt/log_viewer.cpp
+++ b/rpcs3/rpcs3qt/log_viewer.cpp
@@ -4,6 +4,7 @@
#include "gui_settings.h"
#include "syntax_highlighter.h"
#include "config_checker.h"
+#include "Crypto/unzip.h"
#include
#include
@@ -145,7 +146,7 @@ void log_viewer::show_context_menu(const QPoint& pos)
connect(open, &QAction::triggered, this, [this]()
{
- const QString file_path = QFileDialog::getOpenFileName(this, tr("Select log file"), m_path_last, tr("Log files (*.log);;All files (*.*)"));
+ const QString file_path = QFileDialog::getOpenFileName(this, tr("Select log file"), m_path_last, tr("Log files (*.log *.gz);;All files (*.*)"));
if (file_path.isEmpty())
return;
m_path_last = file_path;
@@ -154,14 +155,27 @@ void log_viewer::show_context_menu(const QPoint& pos)
connect(save, &QAction::triggered, this, [this]()
{
- const QString file_path = QFileDialog::getSaveFileName(this, tr("Save to file"), m_path_last, tr("Log files (*.log);;All files (*.*)"));
+ const QString file_path = QFileDialog::getSaveFileName(this, tr("Save to file"), m_path_last, tr("Log files (*.log *.gz);;All files (*.*)"));
if (file_path.isEmpty())
return;
- if (QFile log_file(file_path); log_file.open(QIODevice::WriteOnly | QIODevice::Truncate))
+ if (fs::file log_file; log_file.open(file_path.toStdString(), fs::rewrite))
{
- log_file.write(m_log_text->toPlainText().toUtf8());
- log_file.close();
+ const QByteArray bytes = m_log_text->toPlainText().toUtf8();
+
+ if (file_path.endsWith(".gz"))
+ {
+ if (!zip(bytes.constData(), bytes.size(), log_file))
+ {
+ gui_log.error("Failed to zip filtered log to file '%s'", file_path);
+ return;
+ }
+ }
+ else
+ {
+ log_file.write(bytes.constData(), bytes.size());
+ }
+
gui_log.success("Exported filtered log to file '%s'", file_path);
}
else
@@ -230,24 +244,43 @@ void log_viewer::show_log()
m_log_text->setPlainText(tr("Loading file..."));
QApplication::processEvents();
- if (QFile file(m_path_last);
- file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text))
- {
- m_gui_settings->SetValue(gui::fd_log_viewer, m_path_last);
+ bool failed = false;
+ if (m_path_last.endsWith(".gz"))
+ {
+ if (fs::file file{m_path_last.toStdString()})
+ {
+ const std::vector decompressed = unzip(file.to_vector());
+ m_full_log = QString::fromUtf8(reinterpret_cast(decompressed.data()), decompressed.size());
+ }
+ else
+ {
+ failed = true;
+ }
+ }
+ else if (QFile file(m_path_last); file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
// TODO: Due to a bug in Qt 6.5.2 QTextStream::readAll is ridiculously slow to the point where it gets stuck on large files.
// In Qt 5.15.2 this was much faster than QFile::readAll. Use QTextStream again once this bug is fixed upstream.
//QTextStream stream(&file);
//m_full_log = stream.readAll();
m_full_log = file.readAll();
- m_full_log.replace('\0', '0');
- file.close();
}
else
+ {
+ failed = true;
+ }
+
+ if (failed)
{
gui_log.error("log_viewer: Failed to open %s", m_path_last);
m_log_text->setPlainText(tr("Failed to open '%0'").arg(m_path_last));
}
+ else
+ {
+ m_gui_settings->SetValue(gui::fd_log_viewer, m_path_last);
+ m_full_log.replace('\0', '0');
+ }
filter_log();
}
@@ -403,7 +436,7 @@ bool log_viewer::is_valid_file(const QMimeData& md, bool save)
const QString suffix = QFileInfo(urls[0].fileName()).suffix().toLower();
- if (suffix == "log")
+ if (suffix == "log" || suffix == "gz")
{
if (save)
{