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)
- - SDL version 2.0.1 or greater, latest version highly recommended
+ - SDL version 2.0.3 or greater, latest version highly recommended
- 15/16 bit color minimum; 24/32 bit color graphics card highly recommended
- Enough RAM for the OS + 256MB RAM for the emulation; 512MB+ highly recommended
- Joysticks or gamepads are highly recommended
@@ -335,7 +335,7 @@
- OpenGL capable video card
- Other architectures (MIPS, PPC, PPC64, etc) have been confirmed to work,
but aren't as well tested as i386/x86_64
- - GNU g++ v/4.7 or Clang v/3.3 (with C++11 support) and the make utility are required for compiling
+
- GNU g++ v/4.9 or Clang v/3.3 (with C++11 support) and the make utility are required for compiling
the Stella source code
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