mirror of https://github.com/stella-emu/stella.git
Fixed bug when loading from ZIP files created in OSX. In some
cases, these archives contain directories named '__MACOSX' which contain link files that were being erroneously detected as actual ROMs. Added FilesystemNode::isFile() method, and updated several places in the code to use it. Previously, determining whether something was a file was simply testing if it wasn't a directory, but this logic isn't always valid (it's possible to be neither a regular file *nor* a directory). Bumped version # for RC release. It's getting very close ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2477 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
042afc2edb
commit
aa544ecfe9
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#define STELLA_VERSION "3.7_beta1"
|
#define STELLA_VERSION "3.7_rc1"
|
||||||
#define STELLA_BUILD atoi("$Rev$" + 6)
|
#define STELLA_BUILD atoi("$Rev$" + 6)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -138,7 +138,7 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
theOSystem->logMessage("Showing output from 'rominfo' ...\n", 2);
|
theOSystem->logMessage("Showing output from 'rominfo' ...\n", 2);
|
||||||
FilesystemNode romnode(romfile);
|
FilesystemNode romnode(romfile);
|
||||||
if(argc > 1 && romnode.exists() && !romnode.isDirectory())
|
if(argc > 1 && romnode.exists() && romnode.isFile())
|
||||||
theOSystem->logMessage(theOSystem->getROMInfo(romfile), 0);
|
theOSystem->logMessage(theOSystem->getROMInfo(romfile), 0);
|
||||||
else
|
else
|
||||||
theOSystem->logMessage("ERROR: ROM doesn't exist\n", 0);
|
theOSystem->logMessage("ERROR: ROM doesn't exist\n", 0);
|
||||||
|
|
|
@ -623,7 +623,7 @@ string CartDebug::loadSymbolFile(string file)
|
||||||
file += ".sym";
|
file += ".sym";
|
||||||
|
|
||||||
FilesystemNode node(file);
|
FilesystemNode node(file);
|
||||||
if(node.exists() && !node.isDirectory())
|
if(node.exists() && node.isFile())
|
||||||
{
|
{
|
||||||
ifstream in(node.getPath().c_str());
|
ifstream in(node.getPath().c_str());
|
||||||
if(!in.is_open())
|
if(!in.is_open())
|
||||||
|
@ -696,7 +696,7 @@ string CartDebug::loadConfigFile(string file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node.exists() && !node.isDirectory())
|
if(node.exists() && node.isFile())
|
||||||
{
|
{
|
||||||
ifstream in(node.getPath().c_str());
|
ifstream in(node.getPath().c_str());
|
||||||
if(!in.is_open())
|
if(!in.is_open())
|
||||||
|
@ -811,7 +811,7 @@ string CartDebug::saveConfigFile(string file)
|
||||||
myOSystem.romFile()).getParent().getPath() + name + ".cfg");
|
myOSystem.romFile()).getParent().getPath() + name + ".cfg");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!node.isDirectory())
|
if(node.isFile())
|
||||||
{
|
{
|
||||||
ofstream out(node.getPath().c_str());
|
ofstream out(node.getPath().c_str());
|
||||||
if(!out.is_open())
|
if(!out.is_open())
|
||||||
|
|
|
@ -144,6 +144,15 @@ bool FilesystemNode::isDirectory() const
|
||||||
return _realNode->isDirectory();
|
return _realNode->isDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool FilesystemNode::isFile() const
|
||||||
|
{
|
||||||
|
if (_realNode == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _realNode->isFile();
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FilesystemNode::isReadable() const
|
bool FilesystemNode::isReadable() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -202,15 +202,16 @@ class FilesystemNode
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the path refers to a directory or not.
|
* Indicates whether the path refers to a directory or not.
|
||||||
*
|
|
||||||
* @todo Currently we assume that a node that is not a directory
|
|
||||||
* automatically is a file (ignoring things like symlinks or pipes).
|
|
||||||
* That might actually be OK... but we could still add an isFile method.
|
|
||||||
* Or even replace isDirectory by a getType() method that can return values like
|
|
||||||
* kDirNodeType, kFileNodeType, kInvalidNodeType.
|
|
||||||
*/
|
*/
|
||||||
virtual bool isDirectory() const;
|
virtual bool isDirectory() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the path refers to a real file or not.
|
||||||
|
*
|
||||||
|
* Currently, a symlink or pipe is not considered a file.
|
||||||
|
*/
|
||||||
|
virtual bool isFile() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the object referred by this path can be read from or not.
|
* Indicates whether the object referred by this path can be read from or not.
|
||||||
*
|
*
|
||||||
|
@ -317,6 +318,11 @@ class AbstractFilesystemNode
|
||||||
*/
|
*/
|
||||||
virtual bool isDirectory() const = 0;
|
virtual bool isDirectory() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this path refers to a real file or not.
|
||||||
|
*/
|
||||||
|
virtual bool isFile() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the object referred by this path can be read from or not.
|
* Indicates whether the object referred by this path can be read from or not.
|
||||||
*
|
*
|
||||||
|
@ -343,10 +349,6 @@ class AbstractFilesystemNode
|
||||||
*/
|
*/
|
||||||
virtual bool isWritable() const = 0;
|
virtual bool isWritable() const = 0;
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
bool isFile();
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a directory from the given path.
|
Create a directory from the given path.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -861,7 +861,8 @@ bool OSystem::loadFromZIP(const string& filename, uInt8** image, uInt32& size)
|
||||||
unzGetCurrentFileInfo(tz, &ufo, currfile, 1024, 0, 0, 0, 0);
|
unzGetCurrentFileInfo(tz, &ufo, currfile, 1024, 0, 0, 0, 0);
|
||||||
currfile[1023] = '\0';
|
currfile[1023] = '\0';
|
||||||
|
|
||||||
if(strlen(currfile) >= 4)
|
if(strlen(currfile) >= 4 &&
|
||||||
|
!BSPF_startsWithIgnoreCase(filename, "__MACOSX"))
|
||||||
{
|
{
|
||||||
// Grab 3-character extension
|
// Grab 3-character extension
|
||||||
const char* ext = currfile + strlen(currfile) - 4;
|
const char* ext = currfile + strlen(currfile) - 4;
|
||||||
|
|
|
@ -31,7 +31,7 @@ Serializer::Serializer(const string& filename, bool readonly)
|
||||||
if(readonly)
|
if(readonly)
|
||||||
{
|
{
|
||||||
FilesystemNode node(filename);
|
FilesystemNode node(filename);
|
||||||
if(!node.isDirectory() && node.isReadable())
|
if(node.isFile() && node.isReadable())
|
||||||
{
|
{
|
||||||
fstream* str = new fstream(filename.c_str(), ios::in | ios::binary);
|
fstream* str = new fstream(filename.c_str(), ios::in | ios::binary);
|
||||||
if(str && str->is_open())
|
if(str && str->is_open())
|
||||||
|
|
|
@ -370,7 +370,8 @@ void LauncherDialog::loadDirListing()
|
||||||
unzGetCurrentFileInfo(tz, &ufo, filename, 1024, 0, 0, 0, 0);
|
unzGetCurrentFileInfo(tz, &ufo, filename, 1024, 0, 0, 0, 0);
|
||||||
filename[1023] = '\0';
|
filename[1023] = '\0';
|
||||||
|
|
||||||
if(strlen(filename) >= 4)
|
if(strlen(filename) >= 4 &&
|
||||||
|
!BSPF_startsWithIgnoreCase(filename, "__MACOSX"))
|
||||||
{
|
{
|
||||||
// Grab 3-character extension
|
// Grab 3-character extension
|
||||||
const char* ext = filename + strlen(filename) - 4;
|
const char* ext = filename + strlen(filename) - 4;
|
||||||
|
@ -545,7 +546,8 @@ int LauncherDialog::filesInArchive(const string& archive)
|
||||||
unzGetCurrentFileInfo(tz, &ufo, filename, 1024, 0, 0, 0, 0);
|
unzGetCurrentFileInfo(tz, &ufo, filename, 1024, 0, 0, 0, 0);
|
||||||
filename[1023] = '\0';
|
filename[1023] = '\0';
|
||||||
|
|
||||||
if(strlen(filename) >= 4)
|
if(strlen(filename) >= 4 &&
|
||||||
|
!BSPF_startsWithIgnoreCase(filename, "__MACOSX"))
|
||||||
{
|
{
|
||||||
// Grab 3-character extension
|
// Grab 3-character extension
|
||||||
const char* ext = filename + strlen(filename) - 4;
|
const char* ext = filename + strlen(filename) - 4;
|
||||||
|
|
|
@ -142,7 +142,7 @@ void RomAuditDialog::auditRoms()
|
||||||
for(unsigned int idx = 0; idx < files.size(); idx++)
|
for(unsigned int idx = 0; idx < files.size(); idx++)
|
||||||
{
|
{
|
||||||
string extension;
|
string extension;
|
||||||
if(!files[idx].isDirectory() &&
|
if(files[idx].isFile() &&
|
||||||
LauncherFilterDialog::isValidRomName(files[idx].getPath(), extension))
|
LauncherFilterDialog::isValidRomName(files[idx].getPath(), extension))
|
||||||
{
|
{
|
||||||
// Calculate the MD5 so we can get the rest of the info
|
// Calculate the MD5 so we can get the rest of the info
|
||||||
|
|
|
@ -53,8 +53,9 @@ class POSIXFilesystemNode : public AbstractFilesystemNode
|
||||||
/**
|
/**
|
||||||
* Creates a POSIXFilesystemNode for a given path.
|
* Creates a POSIXFilesystemNode for a given path.
|
||||||
*
|
*
|
||||||
* @param path String with the path the new node should point to.
|
* @param path String with the path the new node should point to.
|
||||||
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
|
* @param verify true if the isValid and isDirectory/isFile flags should
|
||||||
|
* be verified during the construction.
|
||||||
*/
|
*/
|
||||||
POSIXFilesystemNode(const string& path, bool verify);
|
POSIXFilesystemNode(const string& path, bool verify);
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ class POSIXFilesystemNode : public AbstractFilesystemNode
|
||||||
const string& getPath() const { return _path; }
|
const string& getPath() const { return _path; }
|
||||||
string getRelativePath() const;
|
string getRelativePath() const;
|
||||||
bool isDirectory() const { return _isDirectory; }
|
bool isDirectory() const { return _isDirectory; }
|
||||||
|
bool isFile() const { return _isFile; }
|
||||||
bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
|
bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
|
||||||
bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
|
bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
|
||||||
|
|
||||||
|
@ -74,11 +76,13 @@ class POSIXFilesystemNode : public AbstractFilesystemNode
|
||||||
string _displayName;
|
string _displayName;
|
||||||
string _path;
|
string _path;
|
||||||
bool _isDirectory;
|
bool _isDirectory;
|
||||||
|
bool _isFile;
|
||||||
bool _isValid;
|
bool _isValid;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Tests and sets the _isValid and _isDirectory flags, using the stat() function.
|
* Tests and sets the _isValid and _isDirectory/_isFile flags,
|
||||||
|
* using the stat() function.
|
||||||
*/
|
*/
|
||||||
virtual void setFlags();
|
virtual void setFlags();
|
||||||
};
|
};
|
||||||
|
@ -114,7 +118,13 @@ void POSIXFilesystemNode::setFlags()
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
_isValid = (0 == stat(_path.c_str(), &st));
|
_isValid = (0 == stat(_path.c_str(), &st));
|
||||||
_isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
|
if(_isValid)
|
||||||
|
{
|
||||||
|
_isDirectory = S_ISDIR(st.st_mode);
|
||||||
|
_isFile = S_ISREG(st.st_mode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_isDirectory = _isFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -125,6 +135,7 @@ POSIXFilesystemNode::POSIXFilesystemNode()
|
||||||
_displayName = _path;
|
_displayName = _path;
|
||||||
_isValid = true;
|
_isValid = true;
|
||||||
_isDirectory = true;
|
_isDirectory = true;
|
||||||
|
_isFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -229,12 +240,18 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(entry._path.c_str(), &st) == 0)
|
if (stat(entry._path.c_str(), &st) == 0)
|
||||||
|
{
|
||||||
entry._isDirectory = S_ISDIR(st.st_mode);
|
entry._isDirectory = S_ISDIR(st.st_mode);
|
||||||
|
entry._isFile = S_ISREG(st.st_mode);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
entry._isDirectory = false;
|
entry._isDirectory = entry._isFile = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
entry._isDirectory = (dp->d_type == DT_DIR);
|
entry._isDirectory = (dp->d_type == DT_DIR);
|
||||||
|
entry._isFile = (dp->d_type == DT_REG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -244,7 +261,7 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Honor the chosen mode
|
// Honor the chosen mode
|
||||||
if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
|
if ((mode == FilesystemNode::kListFilesOnly && !entry._isFile) ||
|
||||||
(mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
|
(mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
|
||||||
const string& getPath() const { return _path; }
|
const string& getPath() const { return _path; }
|
||||||
string getRelativePath() const;
|
string getRelativePath() const;
|
||||||
bool isDirectory() const { return _isDirectory; }
|
bool isDirectory() const { return _isDirectory; }
|
||||||
|
bool isFile() const { return _isFile; }
|
||||||
bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
|
bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
|
||||||
bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
|
bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
|
||||||
|
|
||||||
|
@ -107,6 +108,7 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
|
||||||
string _displayName;
|
string _displayName;
|
||||||
string _path;
|
string _path;
|
||||||
bool _isDirectory;
|
bool _isDirectory;
|
||||||
|
bool _isFile;
|
||||||
bool _isPseudoRoot;
|
bool _isPseudoRoot;
|
||||||
bool _isValid;
|
bool _isValid;
|
||||||
|
|
||||||
|
@ -177,12 +179,14 @@ void WindowsFilesystemNode::addFile(AbstractFSList& list, ListMode mode,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false);
|
isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false);
|
||||||
|
isFile = (find_data->dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? true : false);
|
||||||
|
|
||||||
if ((!isDirectory && mode == FilesystemNode::kListDirectoriesOnly) ||
|
if ((isFile && mode == FilesystemNode::kListDirectoriesOnly) ||
|
||||||
(isDirectory && mode == FilesystemNode::kListFilesOnly))
|
(isDirectory && mode == FilesystemNode::kListFilesOnly))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry._isDirectory = isDirectory;
|
entry._isDirectory = isDirectory;
|
||||||
|
entry._isFile = isFile;
|
||||||
entry._displayName = asciiName;
|
entry._displayName = asciiName;
|
||||||
entry._path = base;
|
entry._path = base;
|
||||||
entry._path += asciiName;
|
entry._path += asciiName;
|
||||||
|
@ -221,19 +225,12 @@ const TCHAR* WindowsFilesystemNode::toUnicode(const char* str)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
WindowsFilesystemNode::WindowsFilesystemNode()
|
WindowsFilesystemNode::WindowsFilesystemNode()
|
||||||
{
|
{
|
||||||
_isDirectory = true;
|
|
||||||
#ifndef _WIN32_WCE
|
|
||||||
// Create a virtual root directory for standard Windows system
|
// Create a virtual root directory for standard Windows system
|
||||||
|
_isDirectory = true;
|
||||||
|
_isFile = false;
|
||||||
_isValid = false;
|
_isValid = false;
|
||||||
_path = "";
|
_path = "";
|
||||||
_isPseudoRoot = true;
|
_isPseudoRoot = true;
|
||||||
#else
|
|
||||||
_displayName = "Root";
|
|
||||||
// No need to create a pseudo root directory on Windows CE
|
|
||||||
_isValid = true;
|
|
||||||
_path = "\\";
|
|
||||||
_isPseudoRoot = false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -260,12 +257,12 @@ WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
|
||||||
|
|
||||||
if (fileAttribs == INVALID_FILE_ATTRIBUTES)
|
if (fileAttribs == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
_isDirectory = false;
|
_isDirectory = _isFile = _isValid = false;
|
||||||
_isValid = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
_isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||||
|
_isFile = ((fileAttribs & FILE_ATTRIBUTE_NORMAL) != 0);
|
||||||
_isValid = true;
|
_isValid = true;
|
||||||
|
|
||||||
// Add a trailing backslash, if necessary
|
// Add a trailing backslash, if necessary
|
||||||
|
@ -301,7 +298,6 @@ bool WindowsFilesystemNode::
|
||||||
|
|
||||||
if (_isPseudoRoot)
|
if (_isPseudoRoot)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32_WCE
|
|
||||||
// Drives enumeration
|
// Drives enumeration
|
||||||
TCHAR drive_buffer[100];
|
TCHAR drive_buffer[100];
|
||||||
GetLogicalDriveStrings(sizeof(drive_buffer) / sizeof(TCHAR), drive_buffer);
|
GetLogicalDriveStrings(sizeof(drive_buffer) / sizeof(TCHAR), drive_buffer);
|
||||||
|
@ -316,12 +312,12 @@ bool WindowsFilesystemNode::
|
||||||
drive_name[1] = '\0';
|
drive_name[1] = '\0';
|
||||||
entry._displayName = drive_name;
|
entry._displayName = drive_name;
|
||||||
entry._isDirectory = true;
|
entry._isDirectory = true;
|
||||||
|
entry._isFile = false;
|
||||||
entry._isValid = true;
|
entry._isValid = true;
|
||||||
entry._isPseudoRoot = false;
|
entry._isPseudoRoot = false;
|
||||||
entry._path = toAscii(current_drive);
|
entry._path = toAscii(current_drive);
|
||||||
myList.push_back(new WindowsFilesystemNode(entry));
|
myList.push_back(new WindowsFilesystemNode(entry));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -365,6 +361,7 @@ AbstractFilesystemNode* WindowsFilesystemNode::getParent() const
|
||||||
p->_path = string(start, end - start);
|
p->_path = string(start, end - start);
|
||||||
p->_isValid = true;
|
p->_isValid = true;
|
||||||
p->_isDirectory = true;
|
p->_isDirectory = true;
|
||||||
|
p->_isFile = false;
|
||||||
p->_displayName = lastPathComponent(p->_path);
|
p->_displayName = lastPathComponent(p->_path);
|
||||||
p->_isPseudoRoot = false;
|
p->_isPseudoRoot = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue