diff options
Diffstat (limited to 'src/lib/util/unzip.cpp')
-rw-r--r-- | src/lib/util/unzip.cpp | 362 |
1 files changed, 194 insertions, 168 deletions
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp index 321f4e0b69f..06ab41aae3a 100644 --- a/src/lib/util/unzip.cpp +++ b/src/lib/util/unzip.cpp @@ -8,21 +8,25 @@ ***************************************************************************/ -#include "osdcore.h" #include "unzip.h" +#include "corestr.h" +#include "osdcore.h" + + #include <algorithm> #include <array> #include <cassert> #include <cstring> #include <cstdlib> +#include <mutex> #include <utility> #include <vector> #include <zlib.h> - +namespace util { namespace { /*************************************************************************** CONSTANTS @@ -71,29 +75,8 @@ namespace { #define ZIPCRC 0x0e #define ZIPSIZE 0x12 #define ZIPUNCMP 0x16 - -/** - * @def ZIPFNLN - * - * @brief A macro that defines zipfnln. - */ - #define ZIPFNLN 0x1a - -/** - * @def ZIPXTRALN - * - * @brief A macro that defines zipxtraln. - */ - #define ZIPXTRALN 0x1c - -/** - * @def ZIPNAME - * - * @brief A macro that defines zipname. - */ - #define ZIPNAME 0x1e @@ -115,6 +98,8 @@ public: , m_cd() , m_cd_pos(0) , m_header() + , m_curr_is_dir(false) + , m_curr_name() , m_buffer() { std::memset(&m_header, 0, sizeof(m_header)); @@ -123,6 +108,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 @@ -139,37 +125,65 @@ 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()) { } } - zip_file::error initialize() + archive_file::error initialize() { // read ecd data auto const ziperr = read_ecd(); - if (ziperr != zip_file::error::NONE) + if (ziperr != archive_file::error::NONE) return ziperr; // verify that we can work with this zipfile (no disk spanning allowed) if ((m_ecd.disk_number != m_ecd.cd_start_disk_number) || (m_ecd.cd_disk_entries != m_ecd.cd_total_entries)) - return zip_file::error::UNSUPPORTED; + return archive_file::error::UNSUPPORTED; // allocate memory for the central directory try { m_cd.resize(m_ecd.cd_size + 1); } - catch (...) { return zip_file::error::OUT_OF_MEMORY; } + catch (...) { return archive_file::error::OUT_OF_MEMORY; } // read the central directory std::uint32_t read_length; auto const filerr = m_file->read(&m_cd[0], m_ecd.cd_start_disk_offset, m_ecd.cd_size, read_length); if ((filerr != osd_file::error::NONE) || (read_length != m_ecd.cd_size)) - return (filerr == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR; + return (filerr == osd_file::error::NONE) ? archive_file::error::FILE_TRUNCATED : archive_file::error::FILE_ERROR; - return zip_file::error::NONE; + return archive_file::error::NONE; } - // contained file access - const zip_file::file_header *first_file(); - const zip_file::file_header *next_file(); - zip_file::error decompress(void *buffer, std::uint32_t length); + int first_file() + { + m_cd_pos = 0; + return search(0, std::string(), false, false); + } + int next_file() + { + return search(0, std::string(), false, false); + } + int search(std::uint32_t crc) + { + m_cd_pos = 0; + return search(crc, std::string(), true, false); + } + int search(const std::string &filename) + { + m_cd_pos = 0; + return search(0, filename, false, true); + } + int search(std::uint32_t crc, const std::string &filename) + { + m_cd_pos = 0; + return search(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_header.uncompressed_length; } + std::uint32_t current_crc() const { return m_header.crc; } + + archive_file::error decompress(void *buffer, std::uint32_t length); private: zip_file_impl(const zip_file_impl &) = delete; @@ -177,30 +191,47 @@ private: zip_file_impl &operator=(const zip_file_impl &) = delete; zip_file_impl &operator=(zip_file_impl &&) = delete; - zip_file::error reopen() + int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname); + + archive_file::error reopen() { if (!m_file) { auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length); if (filerr != osd_file::error::NONE) - return zip_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; } - return zip_file::error::NONE; + return archive_file::error::NONE; } // ZIP file parsing - zip_file::error read_ecd(); - zip_file::error get_compressed_data_offset(std::uint64_t &offset); + archive_file::error read_ecd(); + archive_file::error get_compressed_data_offset(std::uint64_t &offset); // decompression interfaces - zip_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length); - zip_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length); + archive_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length); + archive_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length); - struct file_header_int : zip_file::file_header + struct file_header { - std::uint8_t * raw; // pointer to the raw data - std::uint32_t rawlength; // length of the raw data - std::uint8_t saved; // saved byte from after filename + std::uint32_t signature; // central file header signature + std::uint16_t version_created; // version made by + std::uint16_t version_needed; // version needed to extract + std::uint16_t bit_flag; // general purpose bit flag + std::uint16_t compression; // compression method + std::uint16_t file_time; // last mod file time + std::uint16_t file_date; // last mod file date + std::uint32_t crc; // crc-32 + std::uint32_t compressed_length; // compressed size + std::uint32_t uncompressed_length; // uncompressed size + std::uint16_t filename_length; // filename length + std::uint16_t extra_field_length; // extra field length + std::uint16_t file_comment_length; // file comment length + std::uint16_t start_disk_number; // disk number start + std::uint16_t internal_attributes; // internal file attributes + std::uint32_t external_attributes; // external file attributes + std::uint32_t local_header_offset; // relative offset of local header + const char * filename; // filename }; // contains extracted end of central directory information @@ -220,9 +251,10 @@ private: std::uint32_t rawlength; // length of the raw data }; - static constexpr std::size_t DECOMPRESS_BUFSIZE = 16384; - static constexpr std::size_t CACHE_SIZE = 8; // number of open files to cache - static std::array<ptr, CACHE_SIZE> s_cache; + static constexpr std::size_t DECOMPRESS_BUFSIZE = 16384; + static constexpr std::size_t CACHE_SIZE = 8; // number of open files to cache + static std::array<ptr, CACHE_SIZE> s_cache; + static std::mutex s_cache_mutex; const std::string m_filename; // copy of ZIP filename (for caching) osd_file::ptr m_file; // OSD file handle @@ -232,20 +264,32 @@ private: std::vector<std::uint8_t> m_cd; // central directory raw data std::uint32_t m_cd_pos; // position in central directory - file_header_int m_header; // current file header + file_header m_header; // current file header + bool m_curr_is_dir; // current file is directory + std::string m_curr_name; // current file name std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression }; -class zip_file_wrapper : public zip_file +class zip_file_wrapper : public archive_file { public: zip_file_wrapper(zip_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); } virtual ~zip_file_wrapper() { zip_file_impl::close(std::move(m_impl)); } - virtual const file_header *first_file() override { return m_impl->first_file(); } - virtual const file_header *next_file() override { return m_impl->next_file(); } + virtual int first_file() override { return m_impl->first_file(); } + virtual int next_file() override { return m_impl->next_file(); } + + virtual int search(std::uint32_t crc) override { return m_impl->search(crc); } + 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(); } + virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); } private: @@ -268,7 +312,7 @@ private: * @return The word. */ -inline UINT16 read_word(UINT8 *buf) +inline std::uint16_t read_word(std::uint8_t const *buf) { return (buf[1] << 8) | buf[0]; } @@ -283,7 +327,7 @@ inline UINT16 read_word(UINT8 *buf) * @return The double word. */ -inline UINT32 read_dword(UINT8 *buf) +inline std::uint32_t read_dword(std::uint8_t const *buf) { return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; } @@ -296,6 +340,7 @@ inline UINT32 read_dword(UINT8 *buf) /** @brief The zip cache[ zip cache size]. */ std::array<zip_file_impl::ptr, zip_file_impl::CACHE_SIZE> zip_file_impl::s_cache; +std::mutex zip_file_impl::s_cache_mutex; @@ -320,6 +365,7 @@ void zip_file_impl::close(ptr &&zip) zip->m_file.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]) @@ -345,88 +391,63 @@ void zip_file_impl::close(ptr &&zip) in the ZIP -------------------------------------------------*/ -/** - * @fn const zip_file_header *zip_file_first_file(zip_file *zip) - * - * @brief Zip file first file. - * - * @param [in,out] zip If non-null, the zip. - * - * @return null if it fails, else a zip_file_header*. - */ - -const zip_file::file_header *zip_file_impl::first_file() -{ - /* reset the position and go from there */ - m_cd_pos = 0; - return next_file(); -} - - /*------------------------------------------------- zip_file_next_entry - return the next entry in the ZIP -------------------------------------------------*/ -/** - * @fn const zip_file_header *zip_file_next_file(zip_file *zip) - * - * @brief Zip file next file. - * - * @param [in,out] zip If non-null, the zip. - * - * @return null if it fails, else a zip_file_header*. - */ - -const zip_file::file_header *zip_file_impl::next_file() +int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname) { - // fix up any modified data - if (m_header.raw) + // if we're at or past the end, we're done + std::string filename; + while (m_cd_pos <= m_ecd.cd_size) { - m_header.raw[ZIPCFN + m_header.filename_length] = m_header.saved; - m_header.raw = nullptr; - } + // extract file header info + std::uint8_t const *const raw = &m_cd[0] + m_cd_pos; + m_header.signature = read_dword(raw + ZIPCENSIG); + m_header.version_created = read_word (raw + ZIPCVER); + m_header.version_needed = read_word (raw + ZIPCVXT); + m_header.bit_flag = read_word (raw + ZIPCFLG); + m_header.compression = read_word (raw + ZIPCMTHD); + m_header.file_time = read_word (raw + ZIPCTIM); + m_header.file_date = read_word (raw + ZIPCDAT); + m_header.crc = read_dword(raw + ZIPCCRC); + m_header.compressed_length = read_dword(raw + ZIPCSIZ); + m_header.uncompressed_length = read_dword(raw + ZIPCUNC); + m_header.filename_length = read_word (raw + ZIPCFNL); + m_header.extra_field_length = read_word (raw + ZIPCXTL); + m_header.file_comment_length = read_word (raw + ZIPCCML); + m_header.start_disk_number = read_word (raw + ZIPDSK); + m_header.internal_attributes = read_word (raw + ZIPINT); + m_header.external_attributes = read_dword(raw + ZIPEXT); + m_header.local_header_offset = read_dword(raw + ZIPOFST); + m_header.filename = reinterpret_cast<const char *>(raw + ZIPCFN); + + // make sure we have enough data + std::uint32_t const rawlength = ZIPCFN + m_header.filename_length + m_header.extra_field_length + m_header.file_comment_length; + if ((m_cd_pos + rawlength) > m_ecd.cd_size) + break; - // if we're at or past the end, we're done - if (m_cd_pos >= m_ecd.cd_size) - return nullptr; - - // extract file header info - m_header.raw = &m_cd[0] + m_cd_pos; - m_header.rawlength = ZIPCFN; - m_header.signature = read_dword(m_header.raw + ZIPCENSIG); - m_header.version_created = read_word (m_header.raw + ZIPCVER); - m_header.version_needed = read_word (m_header.raw + ZIPCVXT); - m_header.bit_flag = read_word (m_header.raw + ZIPCFLG); - m_header.compression = read_word (m_header.raw + ZIPCMTHD); - m_header.file_time = read_word (m_header.raw + ZIPCTIM); - m_header.file_date = read_word (m_header.raw + ZIPCDAT); - m_header.crc = read_dword(m_header.raw + ZIPCCRC); - m_header.compressed_length = read_dword(m_header.raw + ZIPCSIZ); - m_header.uncompressed_length = read_dword(m_header.raw + ZIPCUNC); - m_header.filename_length = read_word (m_header.raw + ZIPCFNL); - m_header.extra_field_length = read_word (m_header.raw + ZIPCXTL); - m_header.file_comment_length = read_word (m_header.raw + ZIPCCML); - m_header.start_disk_number = read_word (m_header.raw + ZIPDSK); - m_header.internal_attributes = read_word (m_header.raw + ZIPINT); - m_header.external_attributes = read_dword(m_header.raw + ZIPEXT); - m_header.local_header_offset = read_dword(m_header.raw + ZIPOFST); - m_header.filename = reinterpret_cast<const char *>(m_header.raw + ZIPCFN); - - // make sure we have enough data - m_header.rawlength += m_header.filename_length; - m_header.rawlength += m_header.extra_field_length; - m_header.rawlength += m_header.file_comment_length; - if (m_cd_pos + m_header.rawlength > m_ecd.cd_size) - return nullptr; - - // NULL terminate the filename - m_header.saved = m_header.raw[ZIPCFN + m_header.filename_length]; - m_header.raw[ZIPCFN + m_header.filename_length] = 0; - - // advance the position - m_cd_pos += m_header.rawlength; - return &m_header; + // advance the position + m_cd_pos += rawlength; + + // copy the filename filename + bool const is_dir((m_header.filename_length > 0) && (m_header.filename[m_header.filename_length - 1] == '/')); + filename.assign(m_header.filename, m_header.filename_length - (is_dir ? 1 : 0)); + + // check to see if it matches query + bool const crcmatch(search_crc == m_header.crc); + const bool namematch(!core_stricmp(search_filename.c_str(), filename.c_str())); + + bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch); + if (found) + { + m_curr_is_dir = is_dir; + m_curr_name = std::move(filename); + return 0; + } + } + return -1; } @@ -447,22 +468,22 @@ const zip_file::file_header *zip_file_impl::next_file() * @return A zip_error. */ -zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length) +archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length) { - zip_file::error ziperr; + archive_file::error ziperr; std::uint64_t offset; // if we don't have enough buffer, error if (length < m_header.uncompressed_length) - return zip_file::error::BUFFER_TOO_SMALL; + return archive_file::error::BUFFER_TOO_SMALL; // make sure the info in the header aligns with what we know if (m_header.start_disk_number != m_ecd.disk_number) - return zip_file::error::UNSUPPORTED; + return archive_file::error::UNSUPPORTED; // get the compressed data offset ziperr = get_compressed_data_offset(offset); - if (ziperr != zip_file::error::NONE) + if (ziperr != archive_file::error::NONE) return ziperr; // handle compression types @@ -477,7 +498,7 @@ zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length) break; default: - ziperr = zip_file::error::UNSUPPORTED; + ziperr = archive_file::error::UNSUPPORTED; break; } return ziperr; @@ -503,11 +524,11 @@ zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length) * @return The ecd. */ -zip_file::error zip_file_impl::read_ecd() +archive_file::error zip_file_impl::read_ecd() { // make sure the file handle is open auto const ziperr = reopen(); - if (ziperr != zip_file::error::NONE) + if (ziperr != archive_file::error::NONE) return ziperr; // we may need multiple tries @@ -521,13 +542,13 @@ zip_file::error zip_file_impl::read_ecd() // allocate buffer std::unique_ptr<std::uint8_t []> buffer; try { buffer.reset(new std::uint8_t[buflen + 1]); } - catch (...) { return zip_file::error::OUT_OF_MEMORY; } + catch (...) { return archive_file::error::OUT_OF_MEMORY; } // read in one buffers' worth of data std::uint32_t read_length; auto const error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length); if (error != osd_file::error::NONE || read_length != buflen) - return zip_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; // find the ECD signature std::int32_t offset; @@ -556,16 +577,16 @@ zip_file::error zip_file_impl::read_ecd() m_ecd.cd_start_disk_offset = read_dword(&m_ecd.raw[ZIPEOFST]); m_ecd.comment_length = read_word (&m_ecd.raw[ZIPECOML]); m_ecd.comment = reinterpret_cast<const char *>(&m_ecd.raw[ZIPECOM]); - return zip_file::error::NONE; + return archive_file::error::NONE; } // didn't find it; free this buffer and expand our search if (buflen < m_length) buflen *= 2; else - return zip_file::error::BAD_SIGNATURE; + return archive_file::error::BAD_SIGNATURE; } - return zip_file::error::OUT_OF_MEMORY; + return archive_file::error::OUT_OF_MEMORY; } @@ -585,25 +606,25 @@ zip_file::error zip_file_impl::read_ecd() * @return The compressed data offset. */ -zip_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) +archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) { // make sure the file handle is open auto const ziperr = reopen(); - if (ziperr != zip_file::error::NONE) + if (ziperr != archive_file::error::NONE) return ziperr; // now go read the fixed-sized part of the local file header std::uint32_t read_length; auto const error = m_file->read(&m_buffer[0], m_header.local_header_offset, ZIPNAME, read_length); if (error != osd_file::error::NONE || read_length != ZIPNAME) - return (error == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR; + return (error == osd_file::error::NONE) ? archive_file::error::FILE_TRUNCATED : archive_file::error::FILE_ERROR; /* compute the final offset */ offset = m_header.local_header_offset + ZIPNAME; offset += read_word(&m_buffer[ZIPFNLN]); offset += read_word(&m_buffer[ZIPXTRALN]); - return zip_file::error::NONE; + return archive_file::error::NONE; } @@ -630,18 +651,18 @@ zip_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) * @return A zip_error. */ -zip_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length) +archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length) { std::uint32_t read_length; // the data is uncompressed; just read it auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length); if (filerr != osd_file::error::NONE) - return zip_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; else if (read_length != m_header.compressed_length) - return zip_file::error::FILE_TRUNCATED; + return archive_file::error::FILE_TRUNCATED; else - return zip_file::error::NONE; + return archive_file::error::NONE; } @@ -663,14 +684,14 @@ zip_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void * @return A zip_error. */ -zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length) +archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length) { std::uint32_t input_remaining = m_header.compressed_length; int zerr; // make sure we don't need a newer mechanism if (m_header.version_needed > 0x14) - return zip_file::error::UNSUPPORTED; + return archive_file::error::UNSUPPORTED; /* reset the stream */ z_stream stream; @@ -681,7 +702,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void // initialize the decompressor zerr = inflateInit2(&stream, -MAX_WBITS); if (zerr != Z_OK) - return zip_file::error::DECOMPRESS_ERROR; + return archive_file::error::DECOMPRESS_ERROR; // loop until we're done while (1) @@ -692,7 +713,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void if (filerr != osd_file::error::NONE) { inflateEnd(&stream); - return zip_file::error::FILE_ERROR; + return archive_file::error::FILE_ERROR; } offset += read_length; @@ -700,7 +721,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void if (read_length == 0 && input_remaining > 0) { inflateEnd(&stream); - return zip_file::error::FILE_TRUNCATED; + return archive_file::error::FILE_TRUNCATED; } // fill out the input data @@ -719,20 +740,20 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void if (zerr != Z_OK) { inflateEnd(&stream); - return zip_file::error::DECOMPRESS_ERROR; + return archive_file::error::DECOMPRESS_ERROR; } } // finish decompression zerr = inflateEnd(&stream); if (zerr != Z_OK) - return zip_file::error::DECOMPRESS_ERROR; + return archive_file::error::DECOMPRESS_ERROR; /* if anything looks funny, report an error */ if (stream.avail_out > 0 || input_remaining > 0) - return zip_file::error::DECOMPRESS_ERROR; + return archive_file::error::DECOMPRESS_ERROR; - return zip_file::error::NONE; + return archive_file::error::NONE; } } // anonymous namespace @@ -740,6 +761,14 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void /*************************************************************************** + un7z.cpp TRAMPOLINES +***************************************************************************/ + +void m7z_file_cache_clear(); + + + +/*************************************************************************** ZIP FILE ACCESS ***************************************************************************/ @@ -758,10 +787,10 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void * @return A zip_error. */ -zip_file::error zip_file::open(const std::string &filename, ptr &zip) +archive_file::error archive_file::open_zip(const std::string &filename, ptr &result) { // ensure we start with a NULL result - zip.reset(); + result.reset(); // see if we are in the cache, and reopen if so zip_file_impl::ptr newimpl(zip_file_impl::find_cached(filename)); @@ -777,7 +806,7 @@ zip_file::error zip_file::open(const std::string &filename, ptr &zip) try { - zip = std::make_unique<zip_file_wrapper>(std::move(newimpl)); + result = std::make_unique<zip_file_wrapper>(std::move(newimpl)); return error::NONE; } catch (...) @@ -793,18 +822,15 @@ zip_file::error zip_file::open(const std::string &filename, ptr &zip) cache and free all memory -------------------------------------------------*/ -/** - * @fn void zip_file_cache_clear(void) - * - * @brief Zip file cache clear. - */ - -void zip_file::cache_clear() +void archive_file::cache_clear() { zip_file_impl::cache_clear(); + m7z_file_cache_clear(); } -zip_file::~zip_file() +archive_file::~archive_file() { } + +} // namespace util |