diff --git a/Changes.txt b/Changes.txt index 897c712b9..c32bfdc2e 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,7 +12,7 @@ Release History =========================================================================== -4.2 to 4.5: (December xx, 2014) +4.2 to 4.5: (January 1, 2015) * The conversion to C++11 has begun :) From this point on, to build Stella you will need a C++11 compatible compiler (Visual Studio 2013, @@ -27,7 +27,10 @@ (currently unplugged) joysticks from this database. * Added preliminary support for 'WD' (Wickstead Design) bankswitching - scheme. + scheme, used for a previously unreleased prototype ROM. + + * Improved ZIP file handling, so that it now works as a normal + filesystem does (it properly shows nested files and directories). * The debugger 'reset' command now does a complete system reset, instead of simply setting the PC to the reset vector address. diff --git a/docs/index.html b/docs/index.html index 9e87fa858..083397e90 100644 --- a/docs/index.html +++ b/docs/index.html @@ -54,7 +54,7 @@


-
February 1999 - December 2014
+
February 1999 - January 2015
The Stella Team
Stella Homepage
@@ -316,7 +316,7 @@

General (required for all versions of Stella)

diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index 8ebc6aa41..6bbd6c71a 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -17,6 +17,8 @@ // $Id$ //============================================================================ +#include + #include "bspf.hxx" #include "OSystem.hxx" #include "FSNodeFactory.hxx" @@ -25,18 +27,29 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNodeZIP::FilesystemNodeZIP() : _error(ZIPERR_NOT_A_FILE), - _numFiles(0) + _numFiles(0), + _isDirectory(false), + _isFile(false) { // We need a name, else the node is invalid - AbstractFSNode* tmp = nullptr; - _realNode = shared_ptr(tmp); + _realNode = shared_ptr(nullptr); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNodeZIP::FilesystemNodeZIP(const string& p) : _error(ZIPERR_NONE), - _numFiles(0) + _numFiles(0), + _isDirectory(false), + _isFile(false) { + // Is this a valid file? + auto isFile = [](const string& file) + { + return BSPF_endsWithIgnoreCase(file, ".a26") || + BSPF_endsWithIgnoreCase(file, ".bin") || + BSPF_endsWithIgnoreCase(file, ".rom"); + }; + // Extract ZIP file and virtual file (if specified) size_t pos = BSPF_findIgnoreCase(p, ".zip"); if(pos == string::npos) @@ -53,61 +66,71 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) return; } - // We always need a virtual file + // We always need a virtual file/path // Either one is given, or we use the first one if(pos+5 < p.length()) - _virtualFile = p.substr(pos+5); + { + _virtualPath = p.substr(pos+5); + _isFile = isFile(_virtualPath); + _isDirectory = !_isFile; + } else if(_numFiles == 1) { bool found = false; while(zip.hasNext() && !found) { - const std::string& file = zip.next(); - if(BSPF_endsWithIgnoreCase(file, ".a26") || - BSPF_endsWithIgnoreCase(file, ".bin") || - BSPF_endsWithIgnoreCase(file, ".rom")) + const string& file = zip.next(); + if(isFile(file)) { - _virtualFile = file; + _virtualPath = file; + _isFile = true; + found = true; } } if(!found) return; } + else + _isDirectory = true; AbstractFSNode* tmp = FilesystemNodeFactory::create(_zipFile, FilesystemNodeFactory::SYSTEM); _realNode = shared_ptr(tmp); - setFlags(_zipFile, _virtualFile, _realNode); + setFlags(_zipFile, _virtualPath, _realNode); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FilesystemNodeZIP::FilesystemNodeZIP(const string& zipfile, const string& virtualfile, - shared_ptr realnode) +FilesystemNodeZIP::FilesystemNodeZIP( + const string& zipfile, const string& virtualpath, + shared_ptr realnode, bool isdir) + : _isDirectory(isdir), + _isFile(!isdir) { - setFlags(zipfile, virtualfile, realnode); + setFlags(zipfile, virtualpath, realnode); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FilesystemNodeZIP::setFlags(const string& zipfile, - const string& virtualfile, + const string& virtualpath, shared_ptr realnode) { _zipFile = zipfile; - _virtualFile = virtualfile; + _virtualPath = virtualpath; _realNode = realnode; _path = _realNode->getPath(); _shortPath = _realNode->getShortPath(); // Is a file component present? - if(_virtualFile.size() != 0) + if(_virtualPath.size() != 0) { - _path += ("/" + _virtualFile); - _shortPath += ("/" + _virtualFile); - _numFiles = 1; + _path += ("/" + _virtualPath); + _shortPath += ("/" + _virtualPath); + _name = lastPathComponent(_path); } + _error = ZIPERR_NONE; if(!_realNode->isFile()) _error = ZIPERR_NOT_A_FILE; @@ -123,11 +146,29 @@ bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode, if(!isDirectory() || _error != ZIPERR_NONE) return false; + set dirs; ZipHandler& zip = open(_zipFile); while(zip.hasNext()) { - FilesystemNodeZIP entry(_path, zip.next(), _realNode); - myList.emplace_back(new FilesystemNodeZIP(entry)); + // Only consider entries that start with '_virtualPath' + const string& next = zip.next(); + if(BSPF_startsWithIgnoreCase(next, _virtualPath)) + { + // First strip off the leading directory + const string& curr = next.substr(_virtualPath == "" ? 0 : _virtualPath.size()+1); + // Only add sub-directory entries once + auto pos = curr.find_first_of("/\\"); + if(pos != string::npos) + dirs.emplace(curr.substr(0, pos)); + else + myList.emplace_back(new FilesystemNodeZIP(_zipFile, next, _realNode, false)); + } + } + for(const auto& dir: dirs) + { + // Prepend previous path + const string& vpath = _virtualPath != "" ? _virtualPath + "/" + dir : dir; + myList.emplace_back(new FilesystemNodeZIP(_zipFile, vpath, _realNode, true)); } return true; @@ -148,7 +189,7 @@ uInt32 FilesystemNodeZIP::read(uInt8*& image) const bool found = false; while(zip.hasNext() && !found) - found = zip.next() == _virtualFile; + found = zip.next() == _virtualPath; return found ? zip.decompress(image) : 0; } @@ -156,7 +197,13 @@ uInt32 FilesystemNodeZIP::read(uInt8*& image) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AbstractFSNode* FilesystemNodeZIP::getParent() const { - return _realNode ? _realNode->getParent() : nullptr; + if(_virtualPath == "") + return _realNode ? _realNode->getParent() : nullptr; + + const char* start = _path.c_str(); + const char* end = lastPathComponent(_path); + + return new FilesystemNodeZIP(string(start, end - start - 1)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index d27d5d94e..eba6c01aa 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -49,11 +49,11 @@ class FilesystemNodeZIP : public AbstractFSNode FilesystemNodeZIP(const string& path); bool exists() const { return _realNode && _realNode->exists(); } - const string& getName() const { return _virtualFile; } - const string& getPath() const { return _path; } - string getShortPath() const { return _shortPath; } - bool isDirectory() const { return _numFiles > 1; } - bool isFile() const { return _numFiles == 1; } + const string& getName() const { return _name; } + const string& getPath() const { return _path; } + string getShortPath() const { return _shortPath; } + bool isDirectory() const { return _isDirectory; } + bool isFile() const { return _isFile; } bool isReadable() const { return _realNode && _realNode->isReadable(); } bool isWritable() const { return false; } @@ -69,16 +69,16 @@ class FilesystemNodeZIP : public AbstractFSNode uInt32 read(uInt8*& image) const; private: - FilesystemNodeZIP(const string& zipfile, const string& virtualfile, - shared_ptr realnode); + FilesystemNodeZIP(const string& zipfile, const string& virtualpath, + shared_ptr realnode, bool isdir); - void setFlags(const string& zipfile, const string& virtualfile, + void setFlags(const string& zipfile, const string& virtualpath, shared_ptr realnode); friend ostream& operator<<(ostream& os, const FilesystemNodeZIP& node) { os << "_zipFile: " << node._zipFile << endl - << "_virtualFile: " << node._virtualFile << endl + << "_virtualPath: " << node._virtualPath << endl << "_path: " << node._path << endl << "_shortPath: " << node._shortPath << endl; return os; @@ -95,18 +95,35 @@ class FilesystemNodeZIP : public AbstractFSNode }; shared_ptr _realNode; - string _zipFile, _virtualFile; - string _path, _shortPath; + string _zipFile, _virtualPath; + string _name, _path, _shortPath; zip_error _error; uInt32 _numFiles; - // ZIP static reference variable responsible for accessing ZIP files + bool _isDirectory, _isFile; + + // ZipHandler static reference variable responsible for accessing ZIP files static unique_ptr myZipHandler; - static ZipHandler& open(const string& file) + inline static ZipHandler& open(const string& file) { myZipHandler->open(file); return *myZipHandler; } + + // Get last component of path + static const char* lastPathComponent(const string& str) + { + if(str.empty()) + return ""; + + const char* start = str.c_str(); + const char* cur = start + str.size() - 2; + + while (cur >= start && !(*cur == '/' || *cur == '\\')) + --cur; + + return cur + 1; + } }; #endif diff --git a/src/common/ZipHandler.cxx b/src/common/ZipHandler.cxx index 616992cc0..e095b0fa2 100644 --- a/src/common/ZipHandler.cxx +++ b/src/common/ZipHandler.cxx @@ -27,7 +27,7 @@ ZipHandler::ZipHandler() : myZip(nullptr) { - for(int cachenum = 0; cachenum < ZIP_CACHE_SIZE; cachenum++) + for(int cachenum = 0; cachenum < ZIP_CACHE_SIZE; ++cachenum) myZipCache[cachenum] = nullptr; } @@ -53,7 +53,7 @@ void ZipHandler::open(const string& filename) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ZipHandler::reset() { - /* reset the position and go from there */ + // Reset the position and go from there if(myZip) myZip->cd_pos = 0; } @@ -183,25 +183,25 @@ bool ZipHandler::stream_read(fstream* stream, void* buffer, uInt64 offset, /*------------------------------------------------- zip_file_open - opens a ZIP file for reading -------------------------------------------------*/ -ZipHandler::zip_error ZipHandler::zip_file_open(const char *filename, zip_file **zip) +ZipHandler::zip_error ZipHandler::zip_file_open(const char* filename, zip_file** zip) { zip_error ziperr = ZIPERR_NONE; uInt32 read_length; - zip_file *newzip; - char *string; + zip_file* newzip; + char* string; int cachenum; bool success; - /* ensure we start with a NULL result */ + // Ensure we start with a NULL result *zip = nullptr; - /* see if we are in the cache, and reopen if so */ - for(cachenum = 0; cachenum < ZIP_CACHE_SIZE; cachenum++) + // See if we are in the cache, and reopen if so + for(cachenum = 0; cachenum < ZIP_CACHE_SIZE; ++cachenum) { - zip_file *cached = myZipCache[cachenum]; + zip_file* cached = myZipCache[cachenum]; - /* if we have a valid entry and it matches our filename, use it and remove - from the cache */ + // If we have a valid entry and it matches our filename, use it and remove + // from the cache if(cached != nullptr && cached->filename != nullptr && strcmp(filename, cached->filename) == 0) { @@ -211,25 +211,25 @@ ZipHandler::zip_error ZipHandler::zip_file_open(const char *filename, zip_file * } } - /* allocate memory for the zip_file structure */ - newzip = (zip_file *)malloc(sizeof(*newzip)); + // Allocate memory for the zip_file structure + newzip = (zip_file*)malloc(sizeof(*newzip)); if (newzip == nullptr) return ZIPERR_OUT_OF_MEMORY; memset(newzip, 0, sizeof(*newzip)); - /* open the file */ + // Open the file if(!stream_open(filename, &newzip->file, newzip->length)) { ziperr = ZIPERR_FILE_ERROR; goto error; } - /* read ecd data */ + // Read ecd data ziperr = read_ecd(newzip); if(ziperr != ZIPERR_NONE) goto error; - /* verify that we can work with this zipfile (no disk spanning allowed) */ + // Verify that we can work with this zipfile (no disk spanning allowed) if (newzip->ecd.disk_number != newzip->ecd.cd_start_disk_number || newzip->ecd.cd_disk_entries != newzip->ecd.cd_total_entries) { @@ -237,15 +237,15 @@ ZipHandler::zip_error ZipHandler::zip_file_open(const char *filename, zip_file * goto error; } - /* allocate memory for the central directory */ - newzip->cd = (uInt8 *)malloc(newzip->ecd.cd_size + 1); + // Allocate memory for the central directory + newzip->cd = (uInt8*)malloc(newzip->ecd.cd_size + 1); if(newzip->cd == nullptr) { ziperr = ZIPERR_OUT_OF_MEMORY; goto error; } - /* read the central directory */ + // Read the central directory success = stream_read(newzip->file, newzip->cd, newzip->ecd.cd_start_disk_offset, newzip->ecd.cd_size, read_length); if(!success || read_length != newzip->ecd.cd_size) @@ -254,8 +254,8 @@ ZipHandler::zip_error ZipHandler::zip_file_open(const char *filename, zip_file * goto error; } - /* make a copy of the filename for caching purposes */ - string = (char *)malloc(strlen(filename) + 1); + // Make a copy of the filename for caching purposes + string = (char*)malloc(strlen(filename) + 1); if (string == nullptr) { ziperr = ZIPERR_OUT_OF_MEMORY; @@ -288,24 +288,24 @@ error: zip_file_close - close a ZIP file and add it to the cache -------------------------------------------------*/ -void ZipHandler::zip_file_close(zip_file *zip) +void ZipHandler::zip_file_close(zip_file* zip) { int cachenum; - /* close the open files */ + // Close the open files if(zip->file) stream_close(&zip->file); - /* find the first NULL entry in the cache */ - for(cachenum = 0; cachenum < ZIP_CACHE_SIZE; cachenum++) - if (myZipCache[cachenum] == nullptr) + // Find the first NULL entry in the cache + for(cachenum = 0; cachenum < ZIP_CACHE_SIZE; ++cachenum) + if(myZipCache[cachenum] == nullptr) break; - /* if no room left in the cache, free the bottommost entry */ + // If no room left in the cache, free the bottommost entry if(cachenum == ZIP_CACHE_SIZE) free_zip_file(myZipCache[--cachenum]); - /* move everyone else down and place us at the top */ + // Move everyone else down and place us at the top if(cachenum != 0) memmove(&myZipCache[1], &myZipCache[0], cachenum * sizeof(myZipCache[0])); myZipCache[0] = zip; @@ -316,15 +316,17 @@ void ZipHandler::zip_file_close(zip_file *zip) zip_file_cache_clear - clear the ZIP file cache and free all memory -------------------------------------------------*/ -void ZipHandler::zip_file_cache_clear(void) +void ZipHandler::zip_file_cache_clear() { - /* clear call cache entries */ - for(int cachenum = 0; cachenum < ZIP_CACHE_SIZE; cachenum++) + // Clear call cache entries + for(int cachenum = 0; cachenum < ZIP_CACHE_SIZE; ++cachenum) + { if(myZipCache[cachenum] != nullptr) { free_zip_file(myZipCache[cachenum]); myZipCache[cachenum] = nullptr; } + } } @@ -336,20 +338,20 @@ void ZipHandler::zip_file_cache_clear(void) zip_file_next_entry - return the next entry in the ZIP -------------------------------------------------*/ -const ZipHandler::zip_file_header* ZipHandler::zip_file_next_file(zip_file *zip) +const ZipHandler::zip_file_header* ZipHandler::zip_file_next_file(zip_file* zip) { - /* fix up any modified data */ + // Fix up any modified data if(zip->header.raw != nullptr) { zip->header.raw[ZIPCFN + zip->header.filename_length] = zip->header.saved; zip->header.raw = nullptr; } - /* if we're at or past the end, we're done */ + // If we're at or past the end, we're done if(zip->cd_pos >= zip->ecd.cd_size) return nullptr; - /* extract file header info */ + // Extract file header info zip->header.raw = zip->cd + zip->cd_pos; zip->header.rawlength = ZIPCFN; zip->header.signature = read_dword(zip->header.raw + ZIPCENSIG); @@ -369,20 +371,20 @@ const ZipHandler::zip_file_header* ZipHandler::zip_file_next_file(zip_file *zip) zip->header.internal_attributes = read_word (zip->header.raw + ZIPINT); zip->header.external_attributes = read_dword(zip->header.raw + ZIPEXT); zip->header.local_header_offset = read_dword(zip->header.raw + ZIPOFST); - zip->header.filename = (char *)zip->header.raw + ZIPCFN; + zip->header.filename = (char*)zip->header.raw + ZIPCFN; - /* make sure we have enough data */ + // Make sure we have enough data zip->header.rawlength += zip->header.filename_length; zip->header.rawlength += zip->header.extra_field_length; zip->header.rawlength += zip->header.file_comment_length; if(zip->cd_pos + zip->header.rawlength > zip->ecd.cd_size) return nullptr; - /* NULL terminate the filename */ + // NULL terminate the filename zip->header.saved = zip->header.raw[ZIPCFN + zip->header.filename_length]; zip->header.raw[ZIPCFN + zip->header.filename_length] = 0; - /* advance the position */ + // Advance the position zip->cd_pos += zip->header.rawlength; return &zip->header; } @@ -392,25 +394,25 @@ const ZipHandler::zip_file_header* ZipHandler::zip_file_next_file(zip_file *zip) from a ZIP into the target buffer -------------------------------------------------*/ ZipHandler::zip_error - ZipHandler::zip_file_decompress(zip_file *zip, void *buffer, uInt32 length) + ZipHandler::zip_file_decompress(zip_file* zip, void* buffer, uInt32 length) { zip_error ziperr; uInt64 offset; - /* if we don't have enough buffer, error */ + // If we don't have enough buffer, error if(length < zip->header.uncompressed_length) return ZIPERR_BUFFER_TOO_SMALL; - /* make sure the info in the header aligns with what we know */ + // Make sure the info in the header aligns with what we know if(zip->header.start_disk_number != zip->ecd.disk_number) return ZIPERR_UNSUPPORTED; - /* get the compressed data offset */ - ziperr = get_compressed_data_offset(zip, &offset); + // Get the compressed data offset + ziperr = get_compressed_data_offset(zip, offset); if(ziperr != ZIPERR_NONE) return ziperr; - /* handle compression types */ + // Handle compression types switch(zip->header.compression) { case 0: @@ -436,14 +438,14 @@ ZipHandler::zip_error free_zip_file - free all the data for a zip_file -------------------------------------------------*/ -void ZipHandler::free_zip_file(zip_file *zip) +void ZipHandler::free_zip_file(zip_file* zip) { if(zip != nullptr) { if(zip->file) stream_close(&zip->file); if(zip->filename != nullptr) - free((void *)zip->filename); + free((void*)zip->filename); if(zip->ecd.raw != nullptr) free(zip->ecd.raw); if(zip->cd != nullptr) @@ -460,27 +462,27 @@ void ZipHandler::free_zip_file(zip_file *zip) read_ecd - read the ECD data -------------------------------------------------*/ -ZipHandler::zip_error ZipHandler::read_ecd(zip_file *zip) +ZipHandler::zip_error ZipHandler::read_ecd(zip_file* zip) { uInt32 buflen = 1024; - uInt8 *buffer; + uInt8* buffer; - /* we may need multiple tries */ + // We may need multiple tries while(buflen < 65536) { uInt32 read_length; Int32 offset; - /* max out the buffer length at the size of the file */ + // Max out the buffer length at the size of the file if(buflen > zip->length) buflen = (uInt32)zip->length; - /* allocate buffer */ - buffer = (uInt8 *)malloc(buflen + 1); + // Allocate buffer + buffer = (uInt8*)malloc(buflen + 1); if(buffer == nullptr) return ZIPERR_OUT_OF_MEMORY; - /* read in one buffers' worth of data */ + // Read in one buffers' worth of data bool success = stream_read(zip->file, buffer, zip->length - buflen, buflen, read_length); if(!success || read_length != buflen) @@ -489,24 +491,24 @@ ZipHandler::zip_error ZipHandler::read_ecd(zip_file *zip) return ZIPERR_FILE_ERROR; } - /* find the ECD signature */ + // Find the ECD signature for(offset = buflen - 22; offset >= 0; offset--) if(buffer[offset + 0] == 'P' && buffer[offset + 1] == 'K' && buffer[offset + 2] == 0x05 && buffer[offset + 3] == 0x06) break; - /* if we found it, fill out the data */ + // If we found it, fill out the data if(offset >= 0) { - /* reuse the buffer as our ECD buffer */ + // Reuse the buffer as our ECD buffer zip->ecd.raw = buffer; zip->ecd.rawlength = buflen - offset; - /* append a NULL terminator to the comment */ + // Append a NULL terminator to the comment memmove(&buffer[0], &buffer[offset], zip->ecd.rawlength); zip->ecd.raw[zip->ecd.rawlength] = 0; - /* extract ecd info */ + // Extract ecd info zip->ecd.signature = read_dword(zip->ecd.raw + ZIPESIG); zip->ecd.disk_number = read_word (zip->ecd.raw + ZIPEDSK); zip->ecd.cd_start_disk_number = read_word (zip->ecd.raw + ZIPECEN); @@ -519,7 +521,7 @@ ZipHandler::zip_error ZipHandler::read_ecd(zip_file *zip) return ZIPERR_NONE; } - /* didn't find it; free this buffer and expand our search */ + // Didn't find it; free this buffer and expand our search free(buffer); if(buflen < zip->length) buflen *= 2; @@ -534,24 +536,24 @@ ZipHandler::zip_error ZipHandler::read_ecd(zip_file *zip) offset of the compressed data -------------------------------------------------*/ ZipHandler::zip_error - ZipHandler::get_compressed_data_offset(zip_file *zip, uInt64 *offset) + ZipHandler::get_compressed_data_offset(zip_file* zip, uInt64& offset) { uInt32 read_length; - /* make sure the file handle is open */ + // Make sure the file handle is open if(zip->file == nullptr && !stream_open(zip->filename, &zip->file, zip->length)) return ZIPERR_FILE_ERROR; - /* now go read the fixed-sized part of the local file header */ + // Now go read the fixed-sized part of the local file header bool success = stream_read(zip->file, zip->buffer, zip->header.local_header_offset, ZIPNAME, read_length); if(!success || read_length != ZIPNAME) return success ? ZIPERR_FILE_TRUNCATED : ZIPERR_FILE_ERROR; - /* compute the final offset */ - *offset = zip->header.local_header_offset + ZIPNAME; - *offset += read_word(zip->buffer + ZIPFNLN); - *offset += read_word(zip->buffer + ZIPXTRALN); + // Compute the final offset + offset = zip->header.local_header_offset + ZIPNAME; + offset += read_word(zip->buffer + ZIPFNLN); + offset += read_word(zip->buffer + ZIPXTRALN); return ZIPERR_NONE; } @@ -565,14 +567,14 @@ ZipHandler::zip_error type 0 data (which is uncompressed) -------------------------------------------------*/ ZipHandler::zip_error - ZipHandler::decompress_data_type_0(zip_file *zip, uInt64 offset, - void *buffer, uInt32 length) + ZipHandler::decompress_data_type_0(zip_file* zip, uInt64 offset, + void* buffer, uInt32 length) { uInt32 read_length; - /* the data is uncompressed; just read it */ - bool success = stream_read(zip->file, buffer, offset, zip->header.compressed_length, - read_length); + // The data is uncompressed; just read it + bool success = stream_read(zip->file, buffer, offset, + zip->header.compressed_length, read_length); if(!success) return ZIPERR_FILE_ERROR; else if(read_length != zip->header.compressed_length) @@ -586,8 +588,8 @@ ZipHandler::zip_error type 8 data (which is deflated) -------------------------------------------------*/ ZipHandler::zip_error - ZipHandler::decompress_data_type_8(zip_file *zip, uInt64 offset, - void *buffer, uInt32 length) + ZipHandler::decompress_data_type_8(zip_file* zip, uInt64 offset, + void* buffer, uInt32 length) { uInt32 input_remaining = zip->header.compressed_length; uInt32 read_length; @@ -597,25 +599,25 @@ ZipHandler::zip_error #if 0 // TODO - check newer versions of ZIP, and determine why this specific // version (0x14) is important - /* make sure we don't need a newer mechanism */ + // Make sure we don't need a newer mechanism if (zip->header.version_needed > 0x14) return ZIPERR_UNSUPPORTED; #endif - /* reset the stream */ + // Reset the stream memset(&stream, 0, sizeof(stream)); stream.next_out = (Bytef *)buffer; stream.avail_out = length; - /* initialize the decompressor */ + // Initialize the decompressor zerr = inflateInit2(&stream, -MAX_WBITS); if(zerr != Z_OK) return ZIPERR_DECOMPRESS_ERROR; - /* loop until we're done */ - while(1) + // Loop until we're done + for(;;) { - /* read in the next chunk of data */ + // Read in the next chunk of data bool success = stream_read(zip->file, zip->buffer, offset, BSPF_min(input_remaining, (uInt32)sizeof(zip->buffer)), read_length); @@ -626,23 +628,23 @@ ZipHandler::zip_error } offset += read_length; - /* if we read nothing, but still have data left, the file is truncated */ + // If we read nothing, but still have data left, the file is truncated if(read_length == 0 && input_remaining > 0) { inflateEnd(&stream); return ZIPERR_FILE_TRUNCATED; } - /* fill out the input data */ + // Fill out the input data stream.next_in = zip->buffer; stream.avail_in = read_length; input_remaining -= read_length; - /* add a dummy byte at end of compressed data */ + // Add a dummy byte at end of compressed data if(input_remaining == 0) stream.avail_in++; - /* now inflate */ + // Now inflate zerr = inflate(&stream, Z_NO_FLUSH); if(zerr == Z_STREAM_END) break; @@ -653,12 +655,12 @@ ZipHandler::zip_error } } - /* finish decompression */ + // Finish decompression zerr = inflateEnd(&stream); if(zerr != Z_OK) return ZIPERR_DECOMPRESS_ERROR; - /* if anything looks funny, report an error */ + // If anything looks funny, report an error if(stream.avail_out > 0 || input_remaining > 0) return ZIPERR_DECOMPRESS_ERROR; diff --git a/src/common/ZipHandler.hxx b/src/common/ZipHandler.hxx index 0ad57ca4c..35f11dde2 100644 --- a/src/common/ZipHandler.hxx +++ b/src/common/ZipHandler.hxx @@ -225,22 +225,22 @@ class ZipHandler /* ----- ZIP file access ----- */ /* open a ZIP file and parse its central directory */ - zip_error zip_file_open(const char *filename, zip_file **zip); + zip_error zip_file_open(const char* filename, zip_file** zip); /* close a ZIP file (may actually be left open due to caching) */ - void zip_file_close(zip_file *zip); + void zip_file_close(zip_file* zip); /* clear out all open ZIP files from the cache */ - void zip_file_cache_clear(void); + void zip_file_cache_clear(); /* ----- contained file access ----- */ /* find the next file in the ZIP */ - const zip_file_header *zip_file_next_file(zip_file *zip); + const zip_file_header* zip_file_next_file(zip_file* zip); /* decompress the most recently found file in the ZIP */ - zip_error zip_file_decompress(zip_file *zip, void *buffer, uInt32 length); + zip_error zip_file_decompress(zip_file* zip, void* buffer, uInt32 length); inline static uInt16 read_word(uInt8* buf) { @@ -253,17 +253,17 @@ class ZipHandler } /* cache management */ - static void free_zip_file(zip_file *zip); + static void free_zip_file(zip_file* zip); /* ZIP file parsing */ - static zip_error read_ecd(zip_file *zip); - static zip_error get_compressed_data_offset(zip_file *zip, uInt64 *offset); + static zip_error read_ecd(zip_file* zip); + static zip_error get_compressed_data_offset(zip_file* zip, uInt64& offset); /* decompression interfaces */ - static zip_error decompress_data_type_0(zip_file *zip, uInt64 offset, - void *buffer, uInt32 length); - static zip_error decompress_data_type_8(zip_file *zip, uInt64 offset, - void *buffer, uInt32 length); + static zip_error decompress_data_type_0(zip_file* zip, uInt64 offset, + void* buffer, uInt32 length); + static zip_error decompress_data_type_8(zip_file* zip, uInt64 offset, + void* buffer, uInt32 length); private: zip_file* myZip; diff --git a/src/unix/FSNodePOSIX.cxx b/src/unix/FSNodePOSIX.cxx index 1dba2dd8f..5c41be267 100644 --- a/src/unix/FSNodePOSIX.cxx +++ b/src/unix/FSNodePOSIX.cxx @@ -19,31 +19,6 @@ #include "FSNodePOSIX.hxx" -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char* lastPathComponent(const string& str) -{ - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') - --cur; - - return cur + 1; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FilesystemNodePOSIX::setFlags() { diff --git a/src/unix/FSNodePOSIX.hxx b/src/unix/FSNodePOSIX.hxx index 6f5864ff7..99671423d 100644 --- a/src/unix/FSNodePOSIX.hxx +++ b/src/unix/FSNodePOSIX.hxx @@ -91,6 +91,30 @@ class FilesystemNodePOSIX : public AbstractFSNode * using the stat() function. */ virtual void setFlags(); + + /** + * Returns the last component of a given path. + * + * Examples: + * /foo/bar.txt would return /bar.txt + * /foo/bar/ would return /bar/ + * + * @param str String containing the path. + * @return Pointer to the first char of the last component inside str. + */ + static const char* lastPathComponent(const string& str) + { + if(str.empty()) + return ""; + + const char* start = str.c_str(); + const char* cur = start + str.size() - 2; + + while (cur >= start && *cur != '/') + --cur; + + return cur + 1; + } }; #endif diff --git a/src/unix/stella.spec b/src/unix/stella.spec index 8f6e89e7e..db18e3584 100644 --- a/src/unix/stella.spec +++ b/src/unix/stella.spec @@ -101,7 +101,7 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version} %_datadir/icons/large/%{name}.png %changelog -* xxx Dec xx 2014 Stephen Anthony 4.5-1 +* Thu Jan 1 2015 Stephen Anthony 4.5-1 - Version 4.5 release * Tue Oct 28 2014 Stephen Anthony 4.2-1