diff options
Diffstat (limited to 'src/lib/util/un7z.cpp')
-rw-r--r-- | src/lib/util/un7z.cpp | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp index b05e4623e57..bca825c1f71 100644 --- a/src/lib/util/un7z.cpp +++ b/src/lib/util/un7z.cpp @@ -10,7 +10,7 @@ // this is based on unzip.c, with modifications needed to use the 7zip library -#include "un7z.h" +#include "unzip.h" #include "corestr.h" #include "unicode.h" @@ -19,15 +19,18 @@ #include "lzma/C/7zCrc.h" #include "lzma/C/7zVersion.h" +#include <algorithm> #include <array> #include <cassert> #include <cstdio> #include <cstdlib> #include <cstring> +#include <mutex> #include <utility> #include <vector> +namespace util { namespace { /*************************************************************************** TYPE DEFINITIONS @@ -98,6 +101,7 @@ public: static ptr find_cached(const std::string &filename) { + std::lock_guard<std::mutex> guard(s_cache_mutex); for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++) { // if we have a valid entry and it matches our filename, use it and remove from the cache @@ -114,10 +118,11 @@ public: static void cache_clear() { // clear call cache entries + std::lock_guard<std::mutex> guard(s_cache_mutex); for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { } } - _7z_file::error initialize(); + archive_file::error initialize(); int first_file() { return search(0, 0, std::string(), false, false); } int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false); } @@ -126,11 +131,12 @@ public: int search(const std::string &filename) { return search(0, 0, filename, false, true); } int search(std::uint32_t crc, const std::string &filename) { return search(0, crc, filename, true, true); } + bool current_is_directory() const { return m_curr_is_dir; } const std::string ¤t_name() const { return m_curr_name; } std::uint64_t current_uncompressed_length() const { return m_curr_length; } std::uint32_t current_crc() const { return m_curr_crc; } - _7z_file::error decompress(void *buffer, std::uint32_t length); + archive_file::error decompress(void *buffer, std::uint32_t length); private: m7z_file_impl(const m7z_file_impl &) = delete; @@ -143,10 +149,12 @@ private: static constexpr std::size_t CACHE_SIZE = 8; static std::array<ptr, CACHE_SIZE> s_cache; + static std::mutex s_cache_mutex; const std::string m_filename; // copy of _7Z filename (for caching) int m_curr_file_idx; // current file index + bool m_curr_is_dir; // current file is directory std::string m_curr_name; // current file name std::uint64_t m_curr_length; // current file uncompressed length std::uint32_t m_curr_crc; // current file crc @@ -170,7 +178,7 @@ private: }; -class m7z_file_wrapper : public _7z_file +class m7z_file_wrapper : public archive_file { public: m7z_file_wrapper(m7z_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); } @@ -183,6 +191,7 @@ public: virtual int search(const std::string &filename) override { return m_impl->search(filename); } virtual int search(std::uint32_t crc, const std::string &filename) override { return m_impl->search(crc, filename); } + virtual bool current_is_directory() const override { return m_impl->current_is_directory(); } virtual const std::string ¤t_name() const override { return m_impl->current_name(); } virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); } virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); } @@ -200,6 +209,7 @@ private: ***************************************************************************/ std::array<m7z_file_impl::ptr, m7z_file_impl::CACHE_SIZE> m7z_file_impl::s_cache; +std::mutex m7z_file_impl::s_cache_mutex; @@ -250,6 +260,7 @@ CFileInStream::CFileInStream() m7z_file_impl::m7z_file_impl(const std::string &filename) : m_filename(filename) , m_curr_file_idx(-1) + , m_curr_is_dir(false) , m_curr_name() , m_curr_length(0) , m_curr_crc(0) @@ -269,11 +280,11 @@ m7z_file_impl::m7z_file_impl(const std::string &filename) } -_7z_file::error m7z_file_impl::initialize() +archive_file::error m7z_file_impl::initialize() { osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length); if (err != osd_file::error::NONE) - return _7z_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; LookToRead_CreateVTable(&m_look_stream, False); m_look_stream.realStream = &m_archive_stream; @@ -286,9 +297,9 @@ _7z_file::error m7z_file_impl::initialize() SRes const res = SzArEx_Open(&m_db, &m_look_stream.s, &m_alloc_imp, &m_alloc_temp_imp); if (res != SZ_OK) - return _7z_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; - return _7z_file::error::NONE; + return archive_file::error::NONE; } @@ -305,6 +316,7 @@ void m7z_file_impl::close(ptr &&archive) archive->m_archive_stream.osdfile.reset(); // find the first NULL entry in the cache + std::lock_guard<std::mutex> guard(s_cache_mutex); std::size_t cachenum; for (cachenum = 0; cachenum < s_cache.size(); cachenum++) if (!s_cache[cachenum]) @@ -331,7 +343,7 @@ void m7z_file_impl::close(ptr &&archive) from a _7Z into the target buffer -------------------------------------------------*/ -_7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length) +archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length) { // make sure the file is open.. if (!m_archive_stream.osdfile) @@ -339,7 +351,7 @@ _7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length) m_archive_stream.currfpos = 0; osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length); if (err != osd_file::error::NONE) - return _7z_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; } size_t offset = 0; @@ -353,11 +365,11 @@ _7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length) &m_alloc_imp, &m_alloc_temp_imp); if (res != SZ_OK) - return _7z_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; std::memcpy(buffer, m_out_buffer + offset, length); - return _7z_file::error::NONE; + return archive_file::error::NONE; } @@ -367,25 +379,22 @@ int m7z_file_impl::search(int i, std::uint32_t search_crc, const std::string &se { const CSzFileItem &f(m_db.db.Files[i]); - // if it's a directory entry we don't care about it.. - if (!f.IsDir) + make_utf8_name(i); + const std::uint64_t size(f.Size); + const std::uint32_t crc(f.Crc); + const bool crcmatch(crc == search_crc); + const bool namematch(!core_stricmp(search_filename.c_str(), &m_utf8_buf[0])); + + const bool found = ((!matchcrc && !matchname) || !f.IsDir) && (!matchcrc || crcmatch) && (!matchname || namematch); + if (found) { - make_utf8_name(i); - const std::uint64_t size(f.Size); - const std::uint32_t crc(f.Crc); - const bool crcmatch(crc == search_crc); - const bool namematch(core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) == 0); - - const bool found = (!matchcrc || crcmatch) && (!matchname || namematch); - if (found) - { - m_curr_file_idx = i; - m_curr_name = &m_utf8_buf[0]; - m_curr_length = size; - m_curr_crc = crc; + m_curr_file_idx = i; + m_curr_is_dir = bool(f.IsDir); + m_curr_name = &m_utf8_buf[0]; + m_curr_length = size; + m_curr_crc = crc; - return i; - } + return i; } } @@ -432,17 +441,13 @@ void m7z_file_impl::make_utf8_name(int index) assert(out_pos < m_utf8_buf.size()); } m_utf8_buf[out_pos++] = '\0'; + m_utf8_buf.resize(out_pos); } } // anonymous namespace -_7z_file::~_7z_file() -{ -} - - -_7z_file::error _7z_file::open(const std::string &filename, ptr &result) +archive_file::error archive_file::open_7z(const std::string &filename, ptr &result) { // ensure we start with a NULL result result.reset(); @@ -477,7 +482,10 @@ _7z_file::error _7z_file::open(const std::string &filename, ptr &result) cache and free all memory -------------------------------------------------*/ -void _7z_file::cache_clear() +void m7z_file_cache_clear() { + // This is a trampoline called from unzip.cpp to avoid the need to have the zip and 7zip code in one file m7z_file_impl::cache_clear(); } + +} // namespace util |