diff options
author | 2016-03-18 19:22:43 +1100 | |
---|---|---|
committer | 2016-03-18 19:32:10 +1100 | |
commit | 100fa28671af455853a6de1b2d7a3499fa6e185c (patch) | |
tree | e1d89e396fc7bc33b5c3b7b075f8138f9396ce3f /src | |
parent | acb27808d4f00b09958e5898966d7917b1debf1a (diff) |
* Remove confusing method from vectorstreams that hide base_ios method (fixes disassembly view)
* Allow std::string to pass through core_file unmolested (reduces temporary allocations)
* Make zip/7z instances of same class with uniform interface
* zippath browsing is broken at the moment
This is another step towards transparent archive support. It's now
possible to access zip and 7z archives with the same code. Nothing is
taking advantage of it yet. There's now some very similar code in
fileio.cpp and clifront.cpp that could be folded at some point.
Diffstat (limited to 'src')
31 files changed, 507 insertions, 580 deletions
diff --git a/src/devices/bus/ti99x/gromport.cpp b/src/devices/bus/ti99x/gromport.cpp index 2b9a66d028a..baa77932f7e 100644 --- a/src/devices/bus/ti99x/gromport.cpp +++ b/src/devices/bus/ti99x/gromport.cpp @@ -2245,43 +2245,46 @@ rpk_socket::rpk_socket(const char* id, int length, UINT8* contents) /* Locate a file in the ZIP container */ -const zip_file::file_header* rpk_reader::find_file(zip_file &zip, const char *filename, UINT32 crc) +int rpk_reader::find_file(util::archive_file &zip, const char *filename, UINT32 crc) { - const zip_file::file_header *header; - for (header = zip.first_file(); header != nullptr; header = zip.next_file()) + for (int header = zip.first_file(); header >= 0; header = zip.next_file()) { - // We don't check for CRC == 0. - if (crc != 0) + // Ignore directories + if (!zip.current_is_directory()) { - // if the CRC and name both match, we're good - // if the CRC matches and the name doesn't, we're still good - if (header->crc == crc) - return header; - } - else - { - if (core_stricmp(header->filename, filename)==0) + // We don't check for CRC == 0. + if (crc != 0) + { + // if the CRC and name both match, we're good + // if the CRC matches and the name doesn't, we're still good + if (zip.current_crc() == crc) + return header; + } + else { - return header; + if (core_stricmp(zip.current_name().c_str(), filename) == 0) + { + return header; + } } } } - return nullptr; + return -1; } /* Load a rom resource and put it in a pcb socket instance. */ -rpk_socket* rpk_reader::load_rom_resource(zip_file &zip, xml_data_node* rom_resource_node, const char* socketname) +rpk_socket* rpk_reader::load_rom_resource(util::archive_file &zip, xml_data_node* rom_resource_node, const char* socketname) { const char* file; const char* crcstr; const char* sha1; - zip_file::error ziperr; + util::archive_file::error ziperr; UINT32 crc; int length; UINT8* contents; - const zip_file::file_header *header; + int header; // find the file attribute (required) file = xml_get_attribute_string(rom_resource_node, "file", nullptr); @@ -2301,9 +2304,9 @@ rpk_socket* rpk_reader::load_rom_resource(zip_file &zip, xml_data_node* rom_reso crc = strtoul(crcstr, nullptr, 16); header = find_file(zip, file, crc); } - if (header == nullptr) throw rpk_exception(RPK_INVALID_FILE_REF, "File not found or CRC check failed"); + if (header < 0) throw rpk_exception(RPK_INVALID_FILE_REF, "File not found or CRC check failed"); - length = header->uncompressed_length; + length = zip.current_uncompressed_length(); // Allocate storage contents = global_alloc_array_clear<UINT8>(length); @@ -2311,9 +2314,9 @@ rpk_socket* rpk_reader::load_rom_resource(zip_file &zip, xml_data_node* rom_reso // and unzip file from the zip file ziperr = zip.decompress(contents, length); - if (ziperr != zip_file::error::NONE) + if (ziperr != util::archive_file::error::NONE) { - if (ziperr == zip_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); + if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); else throw rpk_exception(RPK_ZIP_ERROR); } @@ -2414,15 +2417,14 @@ rpk_socket* rpk_reader::load_ram_resource(emu_options &options, xml_data_node* r rpk* rpk_reader::open(emu_options &options, const char *filename, const char *system_name) { - zip_file::error ziperr; + util::archive_file::error ziperr; - const zip_file::file_header *header; const char *pcb_type; const char *id; const char *uses_name; const char *resource_name; - zip_file::ptr zipfile; + util::archive_file::ptr zipfile; std::vector<char> layout_text; xml_data_node *layout_xml = nullptr; @@ -2442,25 +2444,24 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy try { /* open the ZIP file */ - ziperr = zip_file::open(filename, zipfile); - if (ziperr != zip_file::error::NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT); + ziperr = util::archive_file::open_zip(filename, zipfile); + if (ziperr != util::archive_file::error::NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT); /* find the layout.xml file */ - header = find_file(*zipfile, "layout.xml", 0); - if (header == nullptr) throw rpk_exception(RPK_MISSING_LAYOUT); + if (find_file(*zipfile, "layout.xml", 0) < 0) throw rpk_exception(RPK_MISSING_LAYOUT); /* reserve space for the layout file contents (+1 for the termination) */ - layout_text.resize(header->uncompressed_length + 1); + layout_text.resize(zipfile->current_uncompressed_length() + 1); /* uncompress the layout text */ - ziperr = zipfile->decompress(&layout_text[0], header->uncompressed_length); - if (ziperr != zip_file::error::NONE) + ziperr = zipfile->decompress(&layout_text[0], zipfile->current_uncompressed_length()); + if (ziperr != util::archive_file::error::NONE) { - if (ziperr == zip_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); + if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); else throw rpk_exception(RPK_ZIP_ERROR); } - layout_text[header->uncompressed_length] = '\0'; // Null-terminate + layout_text[zipfile->current_uncompressed_length()] = '\0'; // Null-terminate /* parse the layout text */ layout_xml = xml_string_read(&layout_text[0], nullptr); diff --git a/src/devices/bus/ti99x/gromport.h b/src/devices/bus/ti99x/gromport.h index 9b60425aa06..36900c40045 100644 --- a/src/devices/bus/ti99x/gromport.h +++ b/src/devices/bus/ti99x/gromport.h @@ -454,10 +454,10 @@ public: rpk *open(emu_options &options, const char *filename, const char *system_name); private: - const zip_file::file_header* find_file(zip_file &zip, const char *filename, UINT32 crc); - rpk_socket* load_rom_resource(zip_file &zip, xml_data_node* rom_resource_node, const char* socketname); - rpk_socket* load_ram_resource(emu_options &options, xml_data_node* ram_resource_node, const char* socketname, const char* system_name); - const pcb_type* m_types; + int find_file(util::archive_file &zip, const char *filename, UINT32 crc); + rpk_socket* load_rom_resource(util::archive_file &zip, xml_data_node* rom_resource_node, const char* socketname); + rpk_socket* load_ram_resource(emu_options &options, xml_data_node* ram_resource_node, const char* socketname, const char* system_name); + const pcb_type* m_types; }; class rpk diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index 38e0a5ff9d8..345d6bce3cd 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -365,7 +365,7 @@ floppy_image_format_t *floppy_image_device::identify(std::string filename) util::core_file::ptr fd; std::string revised_path; - osd_file::error err = zippath_fopen(filename.c_str(), OPEN_FLAG_READ, fd, revised_path); + osd_file::error err = util::zippath_fopen(filename.c_str(), OPEN_FLAG_READ, fd, revised_path); if(err != osd_file::error::NONE) { seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to open the image file"); return nullptr; @@ -1004,7 +1004,7 @@ void ui_menu_control_floppy_image::hook_load(std::string filename, bool softlist std::string tmp_path; util::core_file::ptr tmp_file; /* attempt to open the file for writing but *without* create */ - filerr = zippath_fopen(filename.c_str(), OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); + filerr = util::zippath_fopen(filename.c_str(), OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); if(filerr == osd_file::error::NONE) tmp_file.reset(); else @@ -1048,7 +1048,7 @@ void ui_menu_control_floppy_image::handle() state = START_FILE; handle(); } else { - zippath_combine(output_filename, current_directory.c_str(), current_file.c_str()); + util::zippath_combine(output_filename, current_directory.c_str(), current_file.c_str()); output_format = format_array[submenu_result]; do_load_create(); ui_menu::stack_pop(machine()); diff --git a/src/emu/clifront.cpp b/src/emu/clifront.cpp index 79b53e943c7..ee2777257e2 100644 --- a/src/emu/clifront.cpp +++ b/src/emu/clifront.cpp @@ -15,7 +15,6 @@ #include "audit.h" #include "info.h" #include "unzip.h" -#include "un7z.h" #include "validity.h" #include "sound/samples.h" #include "cliopts.h" @@ -266,7 +265,7 @@ int cli_frontend::execute(int argc, char **argv) m_result = MAMERR_FATALERROR; } - _7z_file::cache_clear(); + util::archive_file::cache_clear(); global_free(manager); return m_result; @@ -1000,7 +999,7 @@ void cli_frontend::verifyroms(const char *gamename) } // clear out any cached files - zip_file::cache_clear(); + util::archive_file::cache_clear(); // return an error if none found if (matched == 0) @@ -1092,7 +1091,7 @@ void cli_frontend::verifysamples(const char *gamename) } // clear out any cached files - zip_file::cache_clear(); + util::archive_file::cache_clear(); // return an error if none found if (matched == 0) @@ -1407,7 +1406,7 @@ void cli_frontend::verifysoftware(const char *gamename) } // clear out any cached files - zip_file::cache_clear(); + util::archive_file::cache_clear(); // return an error if none found if (matched == 0) @@ -1529,7 +1528,7 @@ void cli_frontend::verifysoftlist(const char *gamename) } // clear out any cached files - zip_file::cache_clear(); + util::archive_file::cache_clear(); // return an error if none found if (matched == 0) @@ -1761,9 +1760,9 @@ void media_identifier::identify(const char *filename) if (core_filename_ends_with(filename, ".7z")) { // first attempt to examine it as a valid _7Z file - _7z_file::ptr _7z; - _7z_file::error _7zerr = _7z_file::open(filename, _7z); - if (_7zerr == _7z_file::error::NONE && _7z != nullptr) + util::archive_file::ptr _7z; + util::archive_file::error _7zerr = util::archive_file::open_7z(filename, _7z); + if ((_7zerr == util::archive_file::error::NONE) && _7z) { std::vector<std::uint8_t> data; @@ -1771,14 +1770,14 @@ void media_identifier::identify(const char *filename) for (int i = _7z->first_file(); i >= 0; i = _7z->next_file()) { const std::uint64_t length(_7z->current_uncompressed_length()); - if ((length != 0) && (std::uint32_t(length) == length)) + if (!_7z->current_is_directory() && (length != 0) && (std::uint32_t(length) == length)) { // decompress data into RAM and identify it try { data.resize(std::size_t(length)); _7zerr = _7z->decompress(&data[0], std::uint32_t(length)); - if (_7zerr == _7z_file::error::NONE) + if (_7zerr == util::archive_file::error::NONE) identify_data(_7z->current_name().c_str(), &data[0], length); } catch (...) @@ -1792,30 +1791,43 @@ void media_identifier::identify(const char *filename) // clear out any cached files _7z.reset(); - _7z_file::cache_clear(); + util::archive_file::cache_clear(); } else if (core_filename_ends_with(filename, ".zip")) { // first attempt to examine it as a valid ZIP file - zip_file::ptr zip = nullptr; - zip_file::error ziperr = zip_file::open(filename, zip); - if (ziperr == zip_file::error::NONE && zip != nullptr) + util::archive_file::ptr zip; + util::archive_file::error ziperr = util::archive_file::open_zip(filename, zip); + if (ziperr == util::archive_file::error::NONE && zip) { + std::vector<std::uint8_t> data; + // loop over entries in the ZIP, skipping empty files and directories - for (const zip_file::file_header *entry = zip->first_file(); entry != nullptr; entry = zip->next_file()) - if (entry->uncompressed_length != 0) + for (int i = zip->first_file(); i >= 0; i = zip->next_file()) + { + const std::uint64_t length(zip->current_uncompressed_length()); + if (!zip->current_is_directory() && (length != 0) && (std::uint32_t(length) == length)) { // decompress data into RAM and identify it - dynamic_buffer data(entry->uncompressed_length); - ziperr = zip->decompress(&data[0], entry->uncompressed_length); - if (ziperr == zip_file::error::NONE) - identify_data(entry->filename, &data[0], entry->uncompressed_length); + try + { + data.resize(std::size_t(length)); + ziperr = zip->decompress(&data[0], std::uint32_t(length)); + if (ziperr == util::archive_file::error::NONE) + identify_data(zip->current_name().c_str(), &data[0], length); + } + catch (...) + { + // resizing the buffer could cause a bad_alloc if archive contains large files + } + data.clear(); } + } } // clear out any cached files zip.reset(); - zip_file::cache_clear(); + util::archive_file::cache_clear(); } // otherwise, identify as a raw file diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index b8a7ebc4874..2e10b40356e 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -1872,6 +1872,7 @@ static void execute_dump(running_machine &machine, int ref, int params, const ch for (i = offset; i <= endoffset; i += 16) { output.clear(); + output.rdbuf()->clear(); /* print the address */ util::stream_format(output, "%0*X: ", space->logaddrchars(), (UINT32)space->byte_to_address(i)); @@ -2306,6 +2307,7 @@ static void execute_cheatlist(running_machine &machine, int ref, int params, con { active_cheat++; output.clear(); + output.rdbuf()->clear(); stream_format( output, " <cheat desc=\"Possibility %d : %0*X (%0*X)\">\n" @@ -2516,6 +2518,7 @@ static void execute_dasm(running_machine &machine, int ref, int params, const ch offs_t tempaddr; int numbytes = 0; output.clear(); + output.rdbuf()->clear(); /* print the address */ stream_format(output, "%0*X: ", space->logaddrchars(), (UINT32)space->byte_to_address(pcbyte)); diff --git a/src/emu/debug/dvbpoints.cpp b/src/emu/debug/dvbpoints.cpp index 463fc4dbe08..7da6ac4c399 100644 --- a/src/emu/debug/dvbpoints.cpp +++ b/src/emu/debug/dvbpoints.cpp @@ -240,6 +240,7 @@ void debug_view_breakpoints::view_update() if (m_visible.y > 0) { linebuf.clear(); + linebuf.rdbuf()->clear(); linebuf << "ID"; if (m_sortType == &cIndexAscending) linebuf.put('\\'); else if (m_sortType == &cIndexDescending) linebuf.put('/'); @@ -282,6 +283,7 @@ void debug_view_breakpoints::view_update() device_debug::breakpoint *const bp = m_buffer[bpi]; linebuf.clear(); + linebuf.rdbuf()->clear(); util::stream_format(linebuf, "%2X", bp->index()); pad_ostream_to_length(linebuf, tableBreaks[0]); linebuf.put(bp->enabled() ? 'X' : 'O'); diff --git a/src/emu/debug/dvdisasm.cpp b/src/emu/debug/dvdisasm.cpp index b4739fdcbcb..10cb3e75e64 100644 --- a/src/emu/debug/dvdisasm.cpp +++ b/src/emu/debug/dvdisasm.cpp @@ -370,7 +370,7 @@ bool debug_view_disasm::recompute(offs_t pc, int startline, int lines) // allocate disassembly buffer const auto total_bytes = m_total.x * m_total.y; - //m_dasm.clear(); // FIXME + m_dasm.clear(); m_dasm.reserve(total_bytes).seekp(total_bytes); // iterate over lines @@ -388,7 +388,7 @@ bool debug_view_disasm::recompute(offs_t pc, int startline, int lines) // convert back and set the address of this instruction m_byteaddress[instr] = pcbyte; - //m_dasm.clear(); // FIXME + m_dasm.clear(); util::stream_format(m_dasm.seekp(base), source.m_space.is_octal() ? " %0*o " : " %0*X ", source.m_space.logaddrchars()/2*char_num, source.m_space.byte_to_address(pcbyte)); diff --git a/src/emu/debug/dvwpoints.cpp b/src/emu/debug/dvwpoints.cpp index 4720f1dbf3c..8b82a6d3de0 100644 --- a/src/emu/debug/dvwpoints.cpp +++ b/src/emu/debug/dvwpoints.cpp @@ -266,6 +266,7 @@ void debug_view_watchpoints::view_update() if (m_visible.y > 0) { linebuf.clear(); + linebuf.rdbuf()->clear(); linebuf << "ID"; if (m_sortType == &cIndexAscending) linebuf.put('\\'); else if (m_sortType == &cIndexDescending) linebuf.put('/'); @@ -317,6 +318,7 @@ void debug_view_watchpoints::view_update() device_debug::watchpoint *const wp = m_buffer[wpi]; linebuf.clear(); + linebuf.rdbuf()->clear(); util::stream_format(linebuf, "%2X", wp->index()); pad_ostream_to_length(linebuf, tableBreaks[0]); linebuf.put(wp->enabled() ? 'X' : 'O'); diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 216b1af1fca..f225f6cd444 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -158,7 +158,7 @@ void device_image_interface::device_compute_hash(hash_collection &hashes, const image_error_t device_image_interface::set_image_filename(const char *filename) { m_image_name = filename; - zippath_parent(m_working_directory, filename); + util::zippath_parent(m_working_directory, filename); m_basename.assign(m_image_name); size_t loc1 = m_image_name.find_last_of('\\'); @@ -319,7 +319,7 @@ bool device_image_interface::try_change_working_directory(const char *subdir) /* did we successfully identify the directory? */ if (success) - zippath_combine(m_working_directory, m_working_directory.c_str(), subdir); + util::zippath_combine(m_working_directory, m_working_directory.c_str(), subdir); return success; } @@ -611,7 +611,7 @@ image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, cons std::string revised_path; /* attempt to read the file */ - auto const filerr = zippath_fopen(path, open_flags, m_file, revised_path); + auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); /* did the open succeed? */ switch(filerr) @@ -663,7 +663,7 @@ int device_image_interface::reopen_for_write(const char *path) std::string revised_path; /* attempt to open the file for writing*/ - auto const filerr = zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path); + auto const filerr = util::zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path); /* did the open succeed? */ switch(filerr) diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index e0d7cdd7772..2b0f607160c 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -10,7 +10,6 @@ #include "emu.h" #include "unzip.h" -#include "un7z.h" #include "fileio.h" @@ -338,7 +337,7 @@ osd_file::error emu_file::open_next() while (m_iterator.next(m_fullpath, m_filename.c_str())) { // attempt to open the file directly - filerr = util::core_file::open(m_fullpath.c_str(), m_openflags, m_file); + filerr = util::core_file::open(m_fullpath, m_openflags, m_file); if (filerr == osd_file::error::NONE) break; @@ -676,44 +675,37 @@ osd_file::error emu_file::attempt_zipped() m_fullpath = m_fullpath.substr(0, dirsep).append(".zip"); // attempt to open the ZIP file - zip_file::ptr zip; - zip_file::error ziperr = zip_file::open(m_fullpath, zip); + util::archive_file::ptr zip; + util::archive_file::error ziperr = util::archive_file::open_zip(m_fullpath, zip); // chop the .zip back off the filename before continuing m_fullpath = m_fullpath.substr(0, dirsep); // if we failed to open this file, continue scanning - if (ziperr != zip_file::error::NONE) + if (ziperr != util::archive_file::error::NONE) continue; + int header = -1; + // see if we can find a file with the right name and (if available) crc - const zip_file::file_header *header; - for (header = zip->first_file(); header != nullptr; header = zip->next_file()) - if (zip_filename_match(*header, filename) && (!(m_openflags & OPEN_FLAG_HAS_CRC) || header->crc == m_crc)) - break; + if (m_openflags & OPEN_FLAG_HAS_CRC) header = zip->search(m_crc, filename); // if that failed, look for a file with the right crc, but the wrong filename - if (header == nullptr && (m_openflags & OPEN_FLAG_HAS_CRC)) - for (header = zip->first_file(); header != nullptr; header = zip->next_file()) - if (header->crc == m_crc && !zip_header_is_path(*header)) - break; + if (header < 0 && (m_openflags & OPEN_FLAG_HAS_CRC)) header = zip->search(m_crc); // if that failed, look for a file with the right name; reporting a bad checksum // is more helpful and less confusing than reporting "rom not found" - if (header == nullptr) - for (header = zip->first_file(); header != nullptr; header = zip->next_file()) - if (zip_filename_match(*header, filename)) - break; + if (header < 0) header = zip->search(filename); // if we got it, read the data - if (header != nullptr) + if (header >= 0) { m_zipfile = std::move(zip); - m_ziplength = header->uncompressed_length; + m_ziplength = m_zipfile->current_uncompressed_length(); // build a hash with just the CRC m_hashes.reset(); - m_hashes.add_crc(header->crc); + m_hashes.add_crc(m_zipfile->current_crc()); return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? osd_file::error::NONE : load_zipped_file(); } @@ -737,8 +729,8 @@ osd_file::error emu_file::load_zipped_file() m_zipdata.resize(m_ziplength); // read the data into our buffer and return - zip_file::error ziperr = m_zipfile->decompress(&m_zipdata[0], m_zipdata.size()); - if (ziperr != zip_file::error::NONE) + auto const ziperr = m_zipfile->decompress(&m_zipdata[0], m_zipdata.size()); + if (ziperr != util::archive_file::error::NONE) { m_zipdata.clear(); return osd_file::error::FAILURE; @@ -759,29 +751,6 @@ osd_file::error emu_file::load_zipped_file() //------------------------------------------------- -// zip_filename_match - compare zip filename -// to expected filename, ignoring any directory -//------------------------------------------------- - -bool emu_file::zip_filename_match(const zip_file::file_header &header, const std::string &filename) -{ - const char *zipfile = header.filename + header.filename_length - filename.length(); - return (zipfile >= header.filename && core_stricmp(filename.c_str(),zipfile) == 0 && (zipfile == header.filename || zipfile[-1] == '/')); -} - - -//------------------------------------------------- -// zip_header_is_path - check whether filename -// in header is a path -//------------------------------------------------- - -bool emu_file::zip_header_is_path(const zip_file::file_header &header) -{ - const char *zipfile = header.filename + header.filename_length - 1; - return (zipfile >= header.filename && zipfile[0] == '/'); -} - -//------------------------------------------------- // attempt__7zped - attempt to open a .7z file //------------------------------------------------- @@ -810,14 +779,14 @@ osd_file::error emu_file::attempt__7zped() m_fullpath = m_fullpath.substr(0, dirsep).append(".7z"); // attempt to open the _7Z file - _7z_file::ptr _7z; - _7z_file::error _7zerr = _7z_file::open(m_fullpath, _7z); + util::archive_file::ptr _7z; + util::archive_file::error _7zerr = util::archive_file::open_7z(m_fullpath, _7z); // chop the ._7z back off the filename before continuing m_fullpath = m_fullpath.substr(0, dirsep); // if we failed to open this file, continue scanning - if (_7zerr != _7z_file::error::NONE) + if (_7zerr != util::archive_file::error::NONE) continue; int fileno = -1; @@ -826,13 +795,13 @@ osd_file::error emu_file::attempt__7zped() if (m_openflags & OPEN_FLAG_HAS_CRC) fileno = _7z->search(m_crc, filename); // if that failed, look for a file with the right crc, but the wrong filename - if ((fileno == -1) && (m_openflags & OPEN_FLAG_HAS_CRC)) fileno = _7z->search(m_crc); + if ((fileno < 0) && (m_openflags & OPEN_FLAG_HAS_CRC)) fileno = _7z->search(m_crc); // if that failed, look for a file with the right name; reporting a bad checksum // is more helpful and less confusing than reporting "rom not found" - if (fileno == -1) fileno = _7z->search(filename); + if (fileno < 0) fileno = _7z->search(filename); - if (fileno != -1) + if (fileno >= 0) { m__7zfile = std::move(_7z); m__7zlength = m__7zfile->current_uncompressed_length(); @@ -863,8 +832,8 @@ osd_file::error emu_file::load__7zped_file() m__7zdata.resize(m__7zlength); // read the data into our buffer and return - _7z_file::error _7zerr = m__7zfile->decompress(&m__7zdata[0], m__7zdata.size()); - if (_7zerr != _7z_file::error::NONE) + auto const _7zerr = m__7zfile->decompress(&m__7zdata[0], m__7zdata.size()); + if (_7zerr != util::archive_file::error::NONE) { m__7zdata.clear(); return osd_file::error::FAILURE; diff --git a/src/emu/fileio.h b/src/emu/fileio.h index c54c740d686..f45e8be3533 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -15,7 +15,6 @@ #include "corefile.h" #include "hash.h" -#include "unzip.h" // some systems use macros for getc/putc rather than functions #ifdef getc @@ -27,7 +26,7 @@ //************************************************************************** // forward declarations -class _7z_file; +namespace util { class archive_file; } // ======================> path_iterator @@ -147,8 +146,6 @@ private: // internal helpers osd_file::error attempt_zipped(); osd_file::error load_zipped_file(); - bool zip_filename_match(const zip_file::file_header &header, const std::string &filename); - bool zip_header_is_path(const zip_file::file_header &header); osd_file::error attempt__7zped(); osd_file::error load__7zped_file(); @@ -163,11 +160,11 @@ private: UINT32 m_openflags; // flags we used for the open hash_collection m_hashes; // collection of hashes - zip_file::ptr m_zipfile; // ZIP file pointer + std::unique_ptr<util::archive_file> m_zipfile; // ZIP file pointer dynamic_buffer m_zipdata; // ZIP file data UINT64 m_ziplength; // ZIP file length - std::unique_ptr<_7z_file> m__7zfile; // 7Z file pointer + std::unique_ptr<util::archive_file> m__7zfile; // 7Z file pointer dynamic_buffer m__7zdata; // 7Z file data UINT64 m__7zlength; // 7Z file length diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 00db05b59c3..825843c4b10 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -440,7 +440,7 @@ int running_machine::run(bool firstrun) // call all exit callbacks registered call_notifiers(MACHINE_NOTIFY_EXIT); - zip_file::cache_clear(); + util::archive_file::cache_clear(); // close the logfile m_logfile.reset(); diff --git a/src/emu/ui/filesel.cpp b/src/emu/ui/filesel.cpp index 89658407279..a24a3e9a3cf 100644 --- a/src/emu/ui/filesel.cpp +++ b/src/emu/ui/filesel.cpp @@ -474,7 +474,7 @@ ui_menu_file_selector::file_selector_entry *ui_menu_file_selector::append_dirent } // determine the full path - zippath_combine(buffer, m_current_directory.c_str(), dirent->name); + util::zippath_combine(buffer, m_current_directory.c_str(), dirent->name); // create the file selector entry entry = append_entry( @@ -535,7 +535,7 @@ void ui_menu_file_selector::append_entry_menu_item(const file_selector_entry *en void ui_menu_file_selector::populate() { - zippath_directory *directory = nullptr; + util::zippath_directory *directory = nullptr; osd_file::error err; const osd_directory_entry *dirent; const file_selector_entry *entry; @@ -545,7 +545,7 @@ void ui_menu_file_selector::populate() const char *path = m_current_directory.c_str(); // open the directory - err = zippath_opendir(path, &directory); + err = util::zippath_opendir(path, &directory); // clear out the menu entries m_entrylist = nullptr; @@ -581,7 +581,7 @@ void ui_menu_file_selector::populate() // build the menu for each item if (err == osd_file::error::NONE) { - while((dirent = zippath_readdir(directory)) != nullptr) + while((dirent = util::zippath_readdir(directory)) != nullptr) { // append a dirent entry entry = append_dirent_entry(dirent); @@ -611,7 +611,7 @@ void ui_menu_file_selector::populate() customtop = machine().ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; if (directory != nullptr) - zippath_closedir(directory); + util::zippath_closedir(directory); } @@ -656,7 +656,7 @@ void ui_menu_file_selector::handle() case SELECTOR_ENTRY_TYPE_DRIVE: case SELECTOR_ENTRY_TYPE_DIRECTORY: // drive/directory - first check the path - err = zippath_opendir(entry->fullpath, nullptr); + err = util::zippath_opendir(entry->fullpath, nullptr); if (err != osd_file::error::NONE) { // this path is problematic; present the user with an error and bail diff --git a/src/emu/ui/imgcntrl.cpp b/src/emu/ui/imgcntrl.cpp index f0b6f3da5b4..0b44f1f8e8c 100644 --- a/src/emu/ui/imgcntrl.cpp +++ b/src/emu/ui/imgcntrl.cpp @@ -59,12 +59,12 @@ ui_menu_control_device_image::ui_menu_control_device_image(running_machine &mach if (image->exists()) { current_file.assign(image->filename()); - zippath_parent(current_directory, current_file.c_str()); + util::zippath_parent(current_directory, current_file.c_str()); } else current_directory.assign(image->working_directory()); /* check to see if the path exists; if not clear it */ - if (zippath_opendir(current_directory.c_str(), nullptr) != osd_file::error::NONE) + if (util::zippath_opendir(current_directory.c_str(), nullptr) != osd_file::error::NONE) current_directory.clear(); } } @@ -90,7 +90,7 @@ void ui_menu_control_device_image::test_create(bool &can_create, bool &need_conf osd_dir_entry_type file_type; /* assemble the full path */ - zippath_combine(path, current_directory.c_str(), current_file.c_str()); + util::zippath_combine(path, current_directory.c_str(), current_file.c_str()); /* does a file or a directory exist at the path */ entry = osd_stat(path.c_str()); @@ -183,11 +183,11 @@ void ui_menu_control_device_image::handle() case START_FILE: { bool can_create = false; if(image->is_creatable()) { - zippath_directory *directory = nullptr; - osd_file::error err = zippath_opendir(current_directory.c_str(), &directory); - can_create = err == osd_file::error::NONE && !zippath_is_zip(directory); + util::zippath_directory *directory = nullptr; + osd_file::error err = util::zippath_opendir(current_directory.c_str(), &directory); + can_create = err == osd_file::error::NONE && !util::zippath_is_zip(directory); if(directory) - zippath_closedir(directory); + util::zippath_closedir(directory); } submenu_result = -1; ui_menu::stack_push(global_alloc_clear<ui_menu_file_selector>(machine(), container, image, current_directory, current_file, true, image->image_interface()!=nullptr, can_create, &submenu_result)); @@ -335,7 +335,7 @@ void ui_menu_control_device_image::handle() case DO_CREATE: { std::string path; - zippath_combine(path, current_directory.c_str(), current_file.c_str()); + util::zippath_combine(path, current_directory.c_str(), current_file.c_str()); int err = image->create(path.c_str(), nullptr, nullptr); if (err != 0) machine().popmessage("Error: %s", image->error()); diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp index bd48a73d8d8..da3d921ae4a 100644 --- a/src/lib/util/cdrom.cpp +++ b/src/lib/util/cdrom.cpp @@ -244,7 +244,7 @@ cdrom_file *cdrom_open(const char *inputfile) for (i = 0; i < file->cdtoc.numtrks; i++) { - osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname.c_str(), OPEN_FLAG_READ, file->fhandle[i]); + osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]); if (filerr != osd_file::error::NONE) { fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.c_str()); diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp index 5c16d886fe3..e3d34ec3738 100644 --- a/src/lib/util/corefile.cpp +++ b/src/lib/util/corefile.cpp @@ -1084,7 +1084,7 @@ osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64 return an error code -------------------------------------------------*/ -osd_file::error core_file::open(char const *filename, std::uint32_t openflags, ptr &file) +osd_file::error core_file::open(std::string const &filename, std::uint32_t openflags, ptr &file) { try { @@ -1190,7 +1190,7 @@ core_file::~core_file() pointer -------------------------------------------------*/ -osd_file::error core_file::load(char const *filename, void **data, std::uint32_t &length) +osd_file::error core_file::load(std::string const &filename, void **data, std::uint32_t &length) { ptr file; @@ -1219,7 +1219,7 @@ osd_file::error core_file::load(char const *filename, void **data, std::uint32_t return osd_file::error::NONE; } -osd_file::error core_file::load(char const *filename, dynamic_buffer &data) +osd_file::error core_file::load(std::string const &filename, dynamic_buffer &data) { ptr file; diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h index e66545440c2..8f71832411f 100644 --- a/src/lib/util/corefile.h +++ b/src/lib/util/corefile.h @@ -48,7 +48,7 @@ public: // ----- file open/close ----- // open a file with the specified filename - static osd_file::error open(const char *filename, std::uint32_t openflags, ptr &file); + static osd_file::error open(std::string const &filename, std::uint32_t openflags, ptr &file); // open a RAM-based "file" using the given data and length (read-only) static osd_file::error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file); @@ -100,8 +100,8 @@ public: virtual const void *buffer() = 0; // open a file with the specified filename, read it into memory, and return a pointer - static osd_file::error load(const char *filename, void **data, std::uint32_t &length); - static osd_file::error load(const char *filename, dynamic_buffer &data); + static osd_file::error load(std::string const &filename, void **data, std::uint32_t &length); + static osd_file::error load(std::string const &filename, dynamic_buffer &data); // ----- file write ----- diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp index b05e4623e57..8b73faed49b 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,6 +19,7 @@ #include "lzma/C/7zCrc.h" #include "lzma/C/7zVersion.h" +#include <algorithm> #include <array> #include <cassert> #include <cstdio> @@ -28,6 +29,7 @@ #include <vector> +namespace util { namespace { /*************************************************************************** TYPE DEFINITIONS @@ -98,6 +100,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 +117,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 +130,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 +148,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 +177,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 +190,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 +208,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 +259,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 +279,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 +296,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 +315,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 +342,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 +350,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 +364,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 +378,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 +440,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 +481,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 diff --git a/src/lib/util/un7z.h b/src/lib/util/un7z.h deleted file mode 100644 index d2d2e18e25f..00000000000 --- a/src/lib/util/un7z.h +++ /dev/null @@ -1,83 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles, Vas Crabb -/*************************************************************************** - - un7z.h - - 7z file management. - -***************************************************************************/ - -// this is based on unzip.h, with modifications needed to use the 7zip library - -#pragma once - -#ifndef MAME_LIB_UTIL_UN7Z_H -#define MAME_LIB_UTIL_UN7Z_H - -#include "osdcore.h" - -#include <cstdint> -#include <memory> -#include <string> - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -// describes an open _7Z file -class _7z_file -{ -public: - - // Error types - enum class error - { - NONE = 0, - OUT_OF_MEMORY, - FILE_ERROR, - BAD_SIGNATURE, - DECOMPRESS_ERROR, - FILE_TRUNCATED, - FILE_CORRUPT, - UNSUPPORTED, - BUFFER_TOO_SMALL - }; - - typedef std::unique_ptr<_7z_file> ptr; - - - virtual ~_7z_file(); - - /* ----- 7Z file access ----- */ - - // open a 7Z file and parse its central directory - static error open(const std::string &filename, ptr &result); - - // clear out all open 7Z files from the cache - static void cache_clear(); - - - /* ----- contained file access ----- */ - - // iterating over files - virtual int first_file() = 0; - virtual int next_file() = 0; - - // find a file index by crc, filename or both - virtual int search(std::uint32_t crc) = 0; - virtual int search(const std::string &filename) = 0; - virtual int search(std::uint32_t crc, const std::string &filename) = 0; - - // information on most recently found file - virtual const std::string ¤t_name() const = 0; - virtual std::uint64_t current_uncompressed_length() const = 0; - virtual std::uint32_t current_crc() const = 0; - - // decompress the most recently found file in the _7Z - virtual error decompress(void *buffer, std::uint32_t length) = 0; - -}; - -#endif // MAME_LIB_UTIL_UN7Z_H 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 diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h index 2882cda0fc3..5fafaec57a4 100644 --- a/src/lib/util/unzip.h +++ b/src/lib/util/unzip.h @@ -4,7 +4,7 @@ unzip.h - ZIP file management. + archive file management. ***************************************************************************/ @@ -20,12 +20,14 @@ #include <string> +namespace util { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ -// describes an open ZIP file -class zip_file +// describes an open archive file +class archive_file { public: @@ -43,55 +45,45 @@ public: BUFFER_TOO_SMALL }; - // contains extracted file header information - struct file_header - { - 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 - }; - - typedef std::unique_ptr<zip_file> ptr; + typedef std::unique_ptr<archive_file> ptr; - /* ----- ZIP file access ----- */ + /* ----- archive file access ----- */ // open a ZIP file and parse its central directory - static error open(const std::string &filename, ptr &zip); + static error open_zip(const std::string &filename, ptr &zip); + + // open a 7Z file and parse its central directory + static error open_7z(const std::string &filename, ptr &result); - // close a ZIP file (may actually be left open due to caching) - virtual ~zip_file(); + // close an archive file (may actually be left open due to caching) + virtual ~archive_file(); - // clear out all open ZIP files from the cache + // clear out all open files from the cache static void cache_clear(); /* ----- contained file access ----- */ - // find the first file in the ZIP - virtual const file_header *first_file() = 0; + // iterating over files - returns negative on reaching end + virtual int first_file() = 0; + virtual int next_file() = 0; + + // find a file index by crc, filename or both - returns non-negative on match + virtual int search(std::uint32_t crc) = 0; + virtual int search(const std::string &filename) = 0; + virtual int search(std::uint32_t crc, const std::string &filename) = 0; - // find the next file in the ZIP - virtual const file_header *next_file() = 0; + // information on most recently found file + virtual bool current_is_directory() const = 0; + virtual const std::string ¤t_name() const = 0; + virtual std::uint64_t current_uncompressed_length() const = 0; + virtual std::uint32_t current_crc() const = 0; // decompress the most recently found file in the ZIP virtual error decompress(void *buffer, std::uint32_t length) = 0; }; +} // namespace util #endif // MAME_LIB_UTIL_UNZIP_H diff --git a/src/lib/util/vecstream.h b/src/lib/util/vecstream.h index bf144501253..fda218c3e68 100644 --- a/src/lib/util/vecstream.h +++ b/src/lib/util/vecstream.h @@ -320,11 +320,10 @@ public: basic_ivectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } basic_ivectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } - basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_istream<CharT, Traits>::rdbuf()); } + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_istream<CharT, Traits>::rdbuf()); } vector_type const &vec() const { return rdbuf()->vec(); } void vec(const vector_type &content) { rdbuf()->vec(content); } void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } - basic_ivectorstream &clear() { rdbuf()->clear(); return *this; } void swap(basic_ivectorstream &that) { std::basic_istream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); } @@ -342,12 +341,11 @@ public: basic_ovectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } basic_ovectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } - basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_ostream<CharT, Traits>::rdbuf()); } + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_ostream<CharT, Traits>::rdbuf()); } vector_type const &vec() const { return rdbuf()->vec(); } void vec(const vector_type &content) { rdbuf()->vec(content); } void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } - basic_ovectorstream &clear() { rdbuf()->clear(); return *this; } basic_ovectorstream &reserve(typename vector_type::size_type size) { rdbuf()->reserve(size); return *this; } void swap(basic_ovectorstream &that) { std::basic_ostream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); } @@ -366,12 +364,11 @@ public: basic_vectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } basic_vectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } - basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_iostream<CharT, Traits>::rdbuf()); } + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_iostream<CharT, Traits>::rdbuf()); } vector_type const &vec() const { return rdbuf()->vec(); } void vec(const vector_type &content) { rdbuf()->vec(content); } void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } - basic_vectorstream &clear() { rdbuf()->clear(); return *this; } basic_vectorstream &reserve(typename vector_type::size_type size) { rdbuf()->reserve(size); return *this; } void swap(basic_vectorstream &that) { std::basic_iostream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); } diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index 18e2031dcdd..a8fddb64b85 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -18,6 +18,8 @@ #include "osdcore.h" +namespace util { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -66,7 +68,7 @@ public: /** @brief true to called zip first. */ bool called_zip_first; /** @brief The zipfile. */ - zip_file::ptr zipfile; + archive_file::ptr zipfile; /** @brief The zipprefix. */ std::string zipprefix; /** @brief The returned dirlist. */ @@ -78,7 +80,7 @@ public: FUNCTION PROTOTYPES ***************************************************************************/ -static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type); +static int zippath_find_sub_path(archive_file &zipfile, const char *subpath, osd_dir_entry_type *type); static int is_zip_file(const char *path); static int is_zip_file_separator(char c); static int is_7z_file(const char *path); @@ -255,7 +257,7 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa -------------------------------------------------*/ /** - * @fn static osd_file::error file_error_from_zip_error(zip_file::error ziperr) + * @fn static osd_file::error file_error_from_zip_error(archive_file::error ziperr) * * @brief File error from zip error. * @@ -264,26 +266,26 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa * @return A osd_file::error. */ -static osd_file::error file_error_from_zip_error(zip_file::error ziperr) +static osd_file::error file_error_from_zip_error(archive_file::error ziperr) { osd_file::error filerr; switch(ziperr) { - case zip_file::error::NONE: + case archive_file::error::NONE: filerr = osd_file::error::NONE; break; - case zip_file::error::OUT_OF_MEMORY: + case archive_file::error::OUT_OF_MEMORY: filerr = osd_file::error::OUT_OF_MEMORY; break; - case zip_file::error::BAD_SIGNATURE: - case zip_file::error::DECOMPRESS_ERROR: - case zip_file::error::FILE_TRUNCATED: - case zip_file::error::FILE_CORRUPT: - case zip_file::error::UNSUPPORTED: - case zip_file::error::FILE_ERROR: + case archive_file::error::BAD_SIGNATURE: + case archive_file::error::DECOMPRESS_ERROR: + case archive_file::error::FILE_TRUNCATED: + case archive_file::error::FILE_CORRUPT: + case archive_file::error::UNSUPPORTED: + case archive_file::error::FILE_ERROR: filerr = osd_file::error::INVALID_DATA; break; - case zip_file::error::BUFFER_TOO_SMALL: + case archive_file::error::BUFFER_TOO_SMALL: default: filerr = osd_file::error::FAILURE; break; @@ -298,7 +300,7 @@ static osd_file::error file_error_from_zip_error(zip_file::error ziperr) -------------------------------------------------*/ /** - * @fn static osd_file::error create_core_file_from_zip(zip_file *zip, const zip_file_header *header, util::core_file::ptr &file) + * @fn static osd_file::error create_core_file_from_zip(archive_file *zip, util::core_file::ptr &file) * * @brief Creates core file from zip. * @@ -309,27 +311,27 @@ static osd_file::error file_error_from_zip_error(zip_file::error ziperr) * @return The new core file from zip. */ -static osd_file::error create_core_file_from_zip(zip_file &zip, const zip_file::file_header *header, util::core_file::ptr &file) +static osd_file::error create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file) { osd_file::error filerr; - zip_file::error ziperr; + archive_file::error ziperr; void *ptr; - ptr = malloc(header->uncompressed_length); + ptr = malloc(zip.current_uncompressed_length()); if (ptr == nullptr) { filerr = osd_file::error::OUT_OF_MEMORY; goto done; } - ziperr = zip.decompress(ptr, header->uncompressed_length); - if (ziperr != zip_file::error::NONE) + ziperr = zip.decompress(ptr, zip.current_uncompressed_length()); + if (ziperr != archive_file::error::NONE) { filerr = file_error_from_zip_error(ziperr); goto done; } - filerr = util::core_file::open_ram_copy(ptr, header->uncompressed_length, OPEN_FLAG_READ, file); + filerr = util::core_file::open_ram_copy(ptr, zip.current_uncompressed_length(), OPEN_FLAG_READ, file); if (filerr != osd_file::error::NONE) goto done; @@ -360,9 +362,9 @@ done: osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path) { osd_file::error filerr = osd_file::error::NOT_FOUND; - zip_file::error ziperr; - zip_file::ptr zip; - const zip_file::file_header *header; + archive_file::error ziperr; + archive_file::ptr zip; + int header; osd_dir_entry_type entry_type; int len; @@ -379,8 +381,8 @@ osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core if (is_zip_file(mainpath.c_str())) { /* this file might be a zip file - lets take a look */ - ziperr = zip_file::open(mainpath, zip); - if (ziperr == zip_file::error::NONE) + ziperr = archive_file::open_zip(mainpath, zip); + if (ziperr == archive_file::error::NONE) { /* it is a zip file - error if we're not opening for reading */ if (openflags != OPEN_FLAG_READ) @@ -394,20 +396,20 @@ osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core else header = zip->first_file(); - if (header == nullptr) + if (header < 0) { filerr = osd_file::error::NOT_FOUND; goto done; } /* attempt to read the file */ - filerr = create_core_file_from_zip(*zip, header, file); + filerr = create_core_file_from_zip(*zip, file); if (filerr != osd_file::error::NONE) goto done; /* update subpath, if appropriate */ if (subpath.length() == 0) - subpath.assign(header->filename); + subpath.assign(zip->current_name()); /* we're done */ goto done; @@ -656,7 +658,7 @@ static char next_path_char(const char *s, int *pos) -------------------------------------------------*/ /** - * @fn static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const char *subpath, osd_dir_entry_type *type) + * @fn static const zip_file_header *zippath_find_sub_path(archive_file *zipfile, const char *subpath, osd_dir_entry_type *type) * * @brief Zippath find sub path. * @@ -667,13 +669,9 @@ static char next_path_char(const char *s, int *pos) * @return null if it fails, else a zip_file_header*. */ -static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type) +static int zippath_find_sub_path(archive_file &zipfile, const char *subpath, osd_dir_entry_type *type) { - int i, j; - char c1, c2, last_char; - const zip_file::file_header *header; - - for (header = zipfile.first_file(); header != nullptr; header = zipfile.next_file()) + for (int header = zipfile.first_file(); header >= 0; header = zipfile.next_file()) { /* special case */ if (subpath == nullptr) @@ -683,13 +681,12 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con return header; } - i = 0; - j = 0; + // FIXME: how is this actually supposed to work? I'm pretty sure it's broken right now anyway. + int i = 0, j = 0; + char c1, c2, last_char; last_char = '/'; - while(((c1 = next_path_char(header->filename, &i)) == (c2 = next_path_char(subpath, &j))) && - ( c1 != '\0' && c2 != '\0' )) - last_char = c2; - + while(((c1 = next_path_char(zipfile.current_name().c_str(), &i)) == (c2 = next_path_char(subpath, &j))) && (c1 != '\0' && c2 != '\0')) + last_char = c2; if (c2 == '\0') { @@ -710,7 +707,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con if (type != nullptr) *type = ENTTYPE_NONE; - return nullptr; + return -1; } @@ -721,7 +718,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con -------------------------------------------------*/ /** - * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath) + * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file *&zipfile, std::string &newpath) * * @brief Zippath resolve. * @@ -733,7 +730,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con * @return A osd_file::error. */ -static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file::ptr &zipfile, std::string &newpath) +static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath) { osd_file::error err; osd_directory_entry *current_entry = nullptr; @@ -789,7 +786,7 @@ static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &ent /* is this file a ZIP file? */ if ((current_entry_type == ENTTYPE_FILE) && is_zip_file(apath_trimmed.c_str()) - && (zip_file::open(apath_trimmed, zipfile) == zip_file::error::NONE)) + && (archive_file::open_zip(apath_trimmed, zipfile) == archive_file::error::NONE)) { i = strlen(path + apath.length()); while (i > 0 && is_zip_path_separator(path[apath.length() + i - 1])) @@ -943,15 +940,15 @@ void zippath_closedir(zippath_directory *directory) * @return null if it fails, else the relative path. */ -static const char *get_relative_path(zippath_directory *directory, const zip_file::file_header *header) +static const char *get_relative_path(zippath_directory *directory) { const char *result = nullptr; int len = directory->zipprefix.length(); - if ((len <= strlen(header->filename)) - && !strncmp(directory->zipprefix.c_str(), header->filename, len)) + if ((len <= directory->zipfile->current_name().length()) + && !strncmp(directory->zipprefix.c_str(), directory->zipfile->current_name().c_str(), len)) { - result = &header->filename[len]; + result = &directory->zipfile->current_name().c_str()[len]; while(is_zip_file_separator(*result)) result++; } @@ -977,7 +974,7 @@ static const char *get_relative_path(zippath_directory *directory, const zip_fil const osd_directory_entry *zippath_readdir(zippath_directory *directory) { const osd_directory_entry *result = nullptr; - const zip_file::file_header *header; + int header; const char *relpath; const char *separator; const char *s; @@ -1024,7 +1021,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) directory->called_zip_first = true; relpath = nullptr; } - while((header != nullptr) && ((relpath = get_relative_path(directory, header)) == nullptr)); + while((header >= 0) && ((relpath = get_relative_path(directory)) == nullptr)); if (relpath != nullptr) { @@ -1063,7 +1060,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = relpath; directory->returned_entry.type = ENTTYPE_FILE; - directory->returned_entry.size = header->uncompressed_length; + directory->returned_entry.size = directory->zipfile->current_uncompressed_length(); result = &directory->returned_entry; } } @@ -1094,3 +1091,5 @@ int zippath_is_zip(zippath_directory *directory) { return directory->zipfile != nullptr; } + +} // namespace util diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h index d54dd68c38d..653617d66cc 100644 --- a/src/lib/util/zippath.h +++ b/src/lib/util/zippath.h @@ -10,14 +10,16 @@ #pragma once -#ifndef __ZIPPATH_H__ -#define __ZIPPATH_H__ +#ifndef MAME_LIB_UTIL_ZIPPATH_H +#define MAME_LIB_UTIL_ZIPPATH_H #include "corefile.h" #include <string> #include "unzip.h" +namespace util { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -62,6 +64,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory); /* returns TRUE if this path is a ZIP path or FALSE if not */ int zippath_is_zip(zippath_directory *directory); +} // namespace util -#endif /* __ZIPPATH_H__ */ +#endif /* MAME_LIB_UTIL_ZIPPATH_H */ diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp index edf7ee0b14a..95dd285a94d 100644 --- a/src/tools/chdman.cpp +++ b/src/tools/chdman.cpp @@ -333,7 +333,7 @@ public: { m_file.reset(); m_lastfile = m_info.track[tracknum].fname; - osd_file::error filerr = util::core_file::open(m_lastfile.c_str(), OPEN_FLAG_READ, m_file); + osd_file::error filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file); if (filerr != osd_file::error::NONE) report_error(1, "Error opening input file (%s)'", m_lastfile.c_str()); } @@ -1574,7 +1574,7 @@ static void do_create_raw(parameters_t ¶ms) auto input_file_str = params.find(OPTION_INPUT); if (input_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file); + osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", input_file_str->second->c_str()); } @@ -1671,7 +1671,7 @@ static void do_create_hd(parameters_t ¶ms) auto input_file_str = params.find(OPTION_INPUT); if (input_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file); + osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", input_file_str->second->c_str()); } @@ -2240,7 +2240,7 @@ static void do_extract_raw(parameters_t ¶ms) try { // process output file - osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); + osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); @@ -2345,14 +2345,14 @@ static void do_extract_cd(parameters_t ¶ms) } // process output file - osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file); + osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); // process output BIN file if (mode != MODE_GDI) { - filerr = util::core_file::open(output_bin_file_str->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); + filerr = util::core_file::open(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", output_bin_file_str->c_str()); } @@ -2388,7 +2388,7 @@ static void do_extract_cd(parameters_t ¶ms) output_bin_file.reset(); - filerr = util::core_file::open(trackbin_name.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); + filerr = util::core_file::open(trackbin_name, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", trackbin_name.c_str()); @@ -2795,7 +2795,7 @@ static void do_dump_metadata(parameters_t ¶ms) // create the file if (output_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); + osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); if (filerr != osd_file::error::NONE) report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp index d96cf325a7a..b11e7a5e4be 100644 --- a/src/tools/imgtool/stream.cpp +++ b/src/tools/imgtool/stream.cpp @@ -104,24 +104,23 @@ static imgtool_stream *stream_open_zip(const char *zipname, const char *subname, imgfile->imgtype = IMG_MEM; - zip_file::ptr z; - const zip_file::file_header *zipent = nullptr; - zip_file::open(zipname, z); + util::archive_file::ptr z; + util::archive_file::open_zip(zipname, z); if (!z) return nullptr; - zipent = z->first_file(); - while (zipent && subname && strcmp(subname, zipent->filename)) + int zipent = z->first_file(); + while ((zipent >= 0) && subname && strcmp(subname, z->current_name().c_str())) zipent = z->next_file(); - if (!zipent) + if (zipent < 0) return nullptr; - imgfile->filesize = zipent->uncompressed_length; - imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(zipent->uncompressed_length)); + imgfile->filesize = z->current_uncompressed_length(); + imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(z->current_uncompressed_length())); if (!imgfile->buffer) return nullptr; - if (z->decompress(imgfile->buffer, zipent->uncompressed_length) != zip_file::error::NONE) + if (z->decompress(imgfile->buffer, z->current_uncompressed_length()) != util::archive_file::error::NONE) return nullptr; return imgfile.release(); diff --git a/src/tools/pngcmp.cpp b/src/tools/pngcmp.cpp index aa33a421e5d..e34bcf401e4 100644 --- a/src/tools/pngcmp.cpp +++ b/src/tools/pngcmp.cpp @@ -80,7 +80,7 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img int x, y; /* open the source image */ - filerr = util::core_file::open(imgfile1.c_str(), OPEN_FLAG_READ, file); + filerr = util::core_file::open(imgfile1, OPEN_FLAG_READ, file); if (filerr != osd_file::error::NONE) { printf("Could not open %s (%d)\n", imgfile1.c_str(), int(filerr)); @@ -97,7 +97,7 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img } /* open the source image */ - filerr = util::core_file::open(imgfile2.c_str(), OPEN_FLAG_READ, file); + filerr = util::core_file::open(imgfile2, OPEN_FLAG_READ, file); if (filerr != osd_file::error::NONE) { printf("Could not open %s (%d)\n", imgfile2.c_str(), int(filerr)); @@ -170,7 +170,7 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img } /* write the final PNG */ - filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); + filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); if (filerr != osd_file::error::NONE) { printf("Could not open %s (%d)\n", outfilename.c_str(), int(filerr)); diff --git a/src/tools/regrep.cpp b/src/tools/regrep.cpp index 4d02151672b..0c6d11093c6 100644 --- a/src/tools/regrep.cpp +++ b/src/tools/regrep.cpp @@ -565,7 +565,7 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename, util::core_file::ptr file; /* create the indexfile */ - if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE) + if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE) return util::core_file::ptr(); /* print a header */ @@ -735,7 +735,7 @@ static int compare_screenshots(summary_file *curfile) fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", lists[listnum].dir, curfile->name); /* open the file */ - filerr = util::core_file::open(fullname.c_str(), OPEN_FLAG_READ, file); + filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file); /* if that failed, look in the old location */ if (filerr != osd_file::error::NONE) @@ -744,7 +744,7 @@ static int compare_screenshots(summary_file *curfile) fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name); /* open the file */ - filerr = util::core_file::open(fullname.c_str(), OPEN_FLAG_READ, file); + filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file); } /* if that worked, load the file */ @@ -853,7 +853,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir, tempname = string_format("%s" PATH_SEPARATOR "%s", lists[listnum].dir, srcimgname.c_str()); /* open the source image */ - filerr = util::core_file::open(tempname.c_str(), OPEN_FLAG_READ, file); + filerr = util::core_file::open(tempname, OPEN_FLAG_READ, file); if (filerr != osd_file::error::NONE) goto error; @@ -925,7 +925,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir, } /* write the final PNG */ - filerr = util::core_file::open(dstfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); + filerr = util::core_file::open(dstfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); if (filerr != osd_file::error::NONE) goto error; pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr); diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp index a6919631cd8..a940d4522af 100644 --- a/src/tools/romcmp.cpp +++ b/src/tools/romcmp.cpp @@ -490,43 +490,44 @@ static int load_files(int i, int *found, const char *path) /* if not, try to open as a ZIP file */ else { - zip_file::ptr zip; - const zip_file::file_header* zipent; - zip_file::error ziperr; + util::archive_file::ptr zip; + util::archive_file::error ziperr; /* wasn't a directory, so try to open it as a zip file */ - ziperr = zip_file::open(path, zip); - if (ziperr != zip_file::error::NONE) + ziperr = util::archive_file::open_zip(path, zip); + if (ziperr != util::archive_file::error::NONE) { printf("Error, cannot open zip file '%s' !\n", path); return 1; } /* load all files in zip file */ - for (zipent = zip->first_file(); zipent != nullptr; zipent = zip->next_file()) + for (int zipent = zip->first_file(); zipent >= 0; zipent = zip->next_file()) { int size; - size = zipent->uncompressed_length; + size = zip->current_uncompressed_length(); while (size && (size & 1) == 0) size >>= 1; - if (zipent->uncompressed_length == 0) // || (size & ~1)) + if (zip->current_uncompressed_length() == 0) // || (size & ~1)) + { printf("%-23s %-23s ignored (not a ROM)\n", - i ? "" : zipent->filename, i ? zipent->filename : ""); + i ? "" : zip->current_name().c_str(), i ? zip->current_name().c_str() : ""); + } else { fileinfo *file = &files[i][found[i]]; - const char *delim = strrchr(zipent->filename,'/'); + const char *delim = strrchr(zip->current_name().c_str(), '/'); if (delim) strcpy (file->name,delim+1); else - strcpy(file->name,zipent->filename); - file->size = zipent->uncompressed_length; + strcpy(file->name,zip->current_name().c_str()); + file->size = zip->current_uncompressed_length(); if ((file->buf = (unsigned char *)malloc(file->size)) == nullptr) printf("%s: out of memory!\n",file->name); else { - if (zip->decompress(file->buf, file->size) != zip_file::error::NONE) + if (zip->decompress(file->buf, file->size) != util::archive_file::error::NONE) { free(file->buf); file->buf = nullptr; @@ -743,6 +744,6 @@ int CLIB_DECL main(int argc,char *argv[]) } } - zip_file::cache_clear(); + util::archive_file::cache_clear(); return 0; } diff --git a/src/tools/split.cpp b/src/tools/split.cpp index 5151229edd8..586264283d7 100644 --- a/src/tools/split.cpp +++ b/src/tools/split.cpp @@ -119,7 +119,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi splitfilename.assign(basename).append(".split"); // create the split file - filerr = util::core_file::open(splitfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, splitfile); + filerr = util::core_file::open(splitfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, splitfile); if (filerr != osd_file::error::NONE) { fprintf(stderr, "Fatal error: unable to create split file '%s'\n", splitfilename.c_str()); @@ -155,7 +155,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi outfilename = string_format("%s.%03d", basename, partnum); // create it - filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); + filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); if (filerr != osd_file::error::NONE) { printf("\n"); @@ -267,7 +267,7 @@ static int join_file(const char *filename, const char *outname, int write_output if (write_output) { // don't overwrite the original! - filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_READ, outfile); + filerr = util::core_file::open(outfilename, OPEN_FLAG_READ, outfile); if (filerr == osd_file::error::NONE) { outfile.reset(); @@ -276,7 +276,7 @@ static int join_file(const char *filename, const char *outname, int write_output } // open the output for write - filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); + filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); if (filerr != osd_file::error::NONE) { fprintf(stderr, "Fatal error: unable to create file '%s'\n", outfilename.c_str()); diff --git a/src/tools/src2html.cpp b/src/tools/src2html.cpp index 9b3110a212f..38260a62879 100644 --- a/src/tools/src2html.cpp +++ b/src/tools/src2html.cpp @@ -517,7 +517,7 @@ static int output_file(file_type type, int srcrootlen, int dstrootlen, std::stri // open the source file util::core_file::ptr src; - if (util::core_file::open(srcfile.c_str(), OPEN_FLAG_READ, src) != osd_file::error::NONE) + if (util::core_file::open(srcfile, OPEN_FLAG_READ, src) != osd_file::error::NONE) { fprintf(stderr, "Unable to read file '%s'\n", srcfile.c_str()); return 1; @@ -732,7 +732,7 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename, { // create the indexfile util::core_file::ptr file; - if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE) + if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE) return util::core_file::ptr(); // print a header @@ -865,7 +865,7 @@ static bool find_include_file(std::string &srcincpath, int srcrootlen, int dstro // see if we can open it util::core_file::ptr testfile; - if (util::core_file::open(srcincpath.c_str(), OPEN_FLAG_READ, testfile) == osd_file::error::NONE) + if (util::core_file::open(srcincpath, OPEN_FLAG_READ, testfile) == osd_file::error::NONE) { // close the file testfile.reset(); |