mirror of https://github.com/stella-emu/stella.git
Fairly major restructuring of the FSNode classes, removing some static methods
and making them part of the object itself. This is in preparation for a 'ZipFilesystemNode' class, whereby ZIP archives and their contents are supported natively by Stella. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2596 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
ba0ebf3ecb
commit
025100d812
|
@ -42,28 +42,10 @@ FilesystemNode::FilesystemNode(const string& p)
|
|||
_realNode = Common::SharedPtr<AbstractFilesystemNode>(tmp);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::operator<(const FilesystemNode& node) const
|
||||
{
|
||||
if (isDirectory() != node.isDirectory())
|
||||
return isDirectory();
|
||||
|
||||
return BSPF_strcasecmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::operator==(const FilesystemNode& node) const
|
||||
{
|
||||
return BSPF_strcasecmp(getDisplayName().c_str(), node.getDisplayName().c_str()) == 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::exists() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->exists();
|
||||
return _realNode ? _realNode->exists() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -84,13 +66,6 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode, bool hidden) con
|
|||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const string& FilesystemNode::getDisplayName() const
|
||||
{
|
||||
assert(_realNode);
|
||||
return _realNode->getDisplayName();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const string& FilesystemNode::getName() const
|
||||
{
|
||||
|
@ -101,10 +76,7 @@ const string& FilesystemNode::getName() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::hasParent() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->getParent() != 0;
|
||||
return _realNode ? (_realNode->getParent() != 0) : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -137,35 +109,35 @@ string FilesystemNode::getRelativePath() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::isDirectory() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->isDirectory();
|
||||
return _realNode ? _realNode->isDirectory() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::isFile() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->isFile();
|
||||
return _realNode ? _realNode->isFile() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::isReadable() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->isReadable();
|
||||
return _realNode ? _realNode->isReadable() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::isWritable() const
|
||||
{
|
||||
if (_realNode == 0)
|
||||
return false;
|
||||
|
||||
return _realNode->isWritable();
|
||||
return _realNode ? _realNode->isWritable() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::makeDir()
|
||||
{
|
||||
return (_realNode && !_realNode->exists()) ? _realNode->makeDir() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FilesystemNode::rename(const string& newfile)
|
||||
{
|
||||
return (_realNode && _realNode->exists()) ? _realNode->rename(newfile) : false;
|
||||
}
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
* paths (and it's left to them whether / or \ or : is the path separator :-);
|
||||
* but it is also possible to use inodes or vrefs (MacOS 9) or anything else.
|
||||
*
|
||||
* NOTE: Backends still have to provide a way to extract a path from a FSIntern
|
||||
*
|
||||
* You may ask now: "isn't this cheating? Why do we go through all this when we use
|
||||
* a path in the end anyway?!?".
|
||||
* Well, for once as long as we don't provide our own file open/read/write API, we
|
||||
|
@ -48,12 +46,6 @@
|
|||
* And if we ever want to support devices with no FS in the classical sense (Palm...),
|
||||
* we can build upon this.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO - Instead of starting with getRoot(), we should rather add a getDefaultDir()
|
||||
* call that on Unix might return the current dir or the users home dir...
|
||||
* i.e. the root dir is usually not the best starting point for browsing.
|
||||
*/
|
||||
|
||||
#include "Array.hxx"
|
||||
#include "SharedPtr.hxx"
|
||||
|
@ -69,29 +61,8 @@ class AbstractFilesystemNode;
|
|||
class FSList : public Common::Array<FilesystemNode> { };
|
||||
|
||||
/**
|
||||
* FilesystemNode provides an abstraction for file paths, allowing for portable
|
||||
* file system browsing. To this ends, multiple or single roots have to be supported
|
||||
* (compare Unix with a single root, Windows with multiple roots C:, D:, ...).
|
||||
*
|
||||
* To this end, we abstract away from paths; implementations can be based on
|
||||
* paths (and it's left to them whether / or \ or : is the path separator :-);
|
||||
* but it is also possible to use inodes or vrefs (MacOS 9) or anything else.
|
||||
*
|
||||
* NOTE: Backends still have to provide a way to extract a path from a FSIntern
|
||||
*
|
||||
* You may ask now: "isn't this cheating? Why do we go through all this when we use
|
||||
* a path in the end anyway?!?".
|
||||
* Well, for once as long as we don't provide our own file open/read/write API, we
|
||||
* still have to use fopen(). Since all our targets already support fopen(), it should
|
||||
* be possible to get a fopen() compatible string for any file system node.
|
||||
*
|
||||
* Secondly, with this abstraction layer, we still avoid a lot of complications based on
|
||||
* differences in FS roots, different path separators, or even systems with no real
|
||||
* paths (MacOS 9 doesn't even have the notion of a "current directory").
|
||||
* And if we ever want to support devices with no FS in the classical sense (Palm...),
|
||||
* we can build upon this.
|
||||
*
|
||||
* This class acts as a wrapper around the AbstractFilesystemNode class defined in backends/fs.
|
||||
* This class acts as a wrapper around the AbstractFilesystemNode class defined
|
||||
* in backends/fs.
|
||||
*/
|
||||
class FilesystemNode
|
||||
{
|
||||
|
@ -129,16 +100,26 @@ class FilesystemNode
|
|||
* Compare the name of this node to the name of another. Directories
|
||||
* go before normal files.
|
||||
*/
|
||||
bool operator<(const FilesystemNode& node) const;
|
||||
inline bool operator<(const FilesystemNode& node) const
|
||||
{
|
||||
if (isDirectory() != node.isDirectory())
|
||||
return isDirectory();
|
||||
|
||||
return BSPF_strcasecmp(getName().c_str(), node.getName().c_str()) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the name of this node to the name of another, testing for
|
||||
* equality
|
||||
* equality,
|
||||
*/
|
||||
bool operator==(const FilesystemNode& node) const;
|
||||
inline bool operator==(const FilesystemNode& node) const
|
||||
{
|
||||
return BSPF_strcasecmp(getName().c_str(), node.getName().c_str()) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the object referred by this path exists in the filesystem or not.
|
||||
* Indicates whether the object referred by this path exists in the
|
||||
* filesystem or not.
|
||||
*
|
||||
* @return bool true if the path exists, false otherwise.
|
||||
*/
|
||||
|
@ -148,18 +129,11 @@ class FilesystemNode
|
|||
* Return a list of child nodes of this directory node. If called on a node
|
||||
* that does not represent a directory, false is returned.
|
||||
*
|
||||
* @return true if successful, false otherwise (e.g. when the directory does not exist).
|
||||
* @return true if successful, false otherwise (e.g. when the directory
|
||||
* does not exist).
|
||||
*/
|
||||
virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
|
||||
|
||||
/**
|
||||
* Return a human readable string for this node, usable for display (e.g.
|
||||
* in the GUI code). Do *not* rely on it being usable for anything else,
|
||||
* like constructing paths!
|
||||
*
|
||||
* @return the display name
|
||||
*/
|
||||
virtual const string& getDisplayName() const;
|
||||
virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly,
|
||||
bool hidden = false) const;
|
||||
|
||||
/**
|
||||
* Return a string representation of the name of the file. This is can be
|
||||
|
@ -235,7 +209,8 @@ class FilesystemNode
|
|||
* Indicates whether the object referred by this path can be written to or not.
|
||||
*
|
||||
* If the path refers to a directory, writability implies being able to modify
|
||||
* the directory entry (i.e. rename the directory, remove it or write files inside of it).
|
||||
* the directory entry (i.e. rename the directory, remove it or write files
|
||||
* inside of it).
|
||||
*
|
||||
* If the path refers to a file, writability implies being able to write data
|
||||
* to the file.
|
||||
|
@ -244,6 +219,20 @@ class FilesystemNode
|
|||
*/
|
||||
virtual bool isWritable() const;
|
||||
|
||||
/**
|
||||
* Create a directory from the current node path.
|
||||
*
|
||||
* @return bool true if the directory was created, false otherwise.
|
||||
*/
|
||||
virtual bool makeDir();
|
||||
|
||||
/**
|
||||
Rename the current node path with the new given name.
|
||||
*
|
||||
* @return bool true if the node was renamed, false otherwise.
|
||||
*/
|
||||
virtual bool rename(const string& newfile);
|
||||
|
||||
private:
|
||||
Common::SharedPtr<AbstractFilesystemNode> _realNode;
|
||||
FilesystemNode(AbstractFilesystemNode* realNode);
|
||||
|
@ -274,7 +263,8 @@ class AbstractFilesystemNode
|
|||
virtual ~AbstractFilesystemNode() {}
|
||||
|
||||
/*
|
||||
* Indicates whether the object referred by this path exists in the filesystem or not.
|
||||
* Indicates whether the object referred by this path exists in the
|
||||
* filesystem or not.
|
||||
*/
|
||||
virtual bool exists() const = 0;
|
||||
|
||||
|
@ -286,17 +276,11 @@ class AbstractFilesystemNode
|
|||
* @param mode Mode to use while listing the directory.
|
||||
* @param hidden Whether to include hidden files or not in the results.
|
||||
*
|
||||
* @return true if succesful, false otherwise (e.g. when the directory does not exist).
|
||||
* @return true if successful, false otherwise (e.g. when the directory
|
||||
* does not exist).
|
||||
*/
|
||||
virtual bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const = 0;
|
||||
|
||||
/**
|
||||
* Returns a human readable path string.
|
||||
*
|
||||
* @note By default, this method returns the value of getName().
|
||||
*/
|
||||
virtual const string& getDisplayName() const { return getName(); }
|
||||
|
||||
/**
|
||||
* Returns the last component of the path pointed by this FilesystemNode.
|
||||
*
|
||||
|
@ -304,7 +288,8 @@ class AbstractFilesystemNode
|
|||
* /foo/bar.txt would return /bar.txt
|
||||
* /foo/bar/ would return /bar/
|
||||
*
|
||||
* @note This method is very architecture dependent, please check the concrete implementation for more information.
|
||||
* @note This method is very architecture dependent, please check the concrete
|
||||
* implementation for more information.
|
||||
*/
|
||||
virtual const string& getName() const = 0;
|
||||
|
||||
|
@ -346,7 +331,8 @@ class AbstractFilesystemNode
|
|||
* Indicates whether the object referred by this path can be written to or not.
|
||||
*
|
||||
* If the path refers to a directory, writability implies being able to modify
|
||||
* the directory entry (i.e. rename the directory, remove it or write files inside of it).
|
||||
* the directory entry (i.e. rename the directory, remove it or write files
|
||||
* inside of it).
|
||||
*
|
||||
* If the path refers to a file, writability implies being able to write data
|
||||
* to the file.
|
||||
|
@ -356,14 +342,18 @@ class AbstractFilesystemNode
|
|||
virtual bool isWritable() const = 0;
|
||||
|
||||
/**
|
||||
Create a directory from the given path.
|
||||
* Create a directory from the current node path.
|
||||
*
|
||||
* @return bool true if the directory was created, false otherwise.
|
||||
*/
|
||||
static bool makeDir(const string& path);
|
||||
virtual bool makeDir() = 0;
|
||||
|
||||
/**
|
||||
Rename the given file with a new name.
|
||||
Rename the current node path with the new given name.
|
||||
*
|
||||
* @return bool true if the node was renamed, false otherwise.
|
||||
*/
|
||||
static bool renameFile(const string& oldfile, const string& newfile);
|
||||
virtual bool rename(const string& newfile) = 0;
|
||||
|
||||
/**
|
||||
Create an absolute pathname from the given path (if it isn't already
|
||||
|
@ -391,17 +381,6 @@ class AbstractFilesystemNode
|
|||
* @param path The path string to create a FilesystemNode for.
|
||||
*/
|
||||
static AbstractFilesystemNode* makeFileNodePath(const string& path);
|
||||
|
||||
// TODO - the following method isn't actually used anywhere in
|
||||
// the current code (2012-06-14)
|
||||
/**
|
||||
* Returns a special node representing the filesystem root.
|
||||
* The starting point for any file system browsing.
|
||||
*
|
||||
* On Unix, this will be simply the node for / (the root directory).
|
||||
* On Windows, it will be a special node which "contains" all drives (C:, D:, E:).
|
||||
*/
|
||||
static AbstractFilesystemNode* makeRootFileNode();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -386,10 +386,7 @@ void OSystem::setBaseDir(const string& basedir)
|
|||
FilesystemNode node(basedir);
|
||||
myBaseDir = node.getPath();
|
||||
if(!node.isDirectory())
|
||||
{
|
||||
AbstractFilesystemNode::makeDir(myBaseDir);
|
||||
myBaseDir = FilesystemNode(node.getPath()).getPath();
|
||||
}
|
||||
node.makeDir();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -819,7 +816,7 @@ uInt8* OSystem::openROM(string file, string& md5, uInt32& size)
|
|||
{
|
||||
// Get the filename from the rom pathname
|
||||
FilesystemNode node(file);
|
||||
file = node.getDisplayName();
|
||||
file = node.getName();
|
||||
|
||||
props.set(Cartridge_MD5, md5);
|
||||
props.set(Cartridge_Name, file);
|
||||
|
@ -951,10 +948,7 @@ void OSystem::validatePath(string& path, const string& setting,
|
|||
mySettings->getString(setting);
|
||||
FilesystemNode node(s);
|
||||
if(!node.isDirectory())
|
||||
{
|
||||
AbstractFilesystemNode::makeDir(s);
|
||||
node = FilesystemNode(node.getPath());
|
||||
}
|
||||
node.makeDir();
|
||||
path = node.getPath();
|
||||
mySettings->setString(setting, node.getRelativePath());
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ void BrowserDialog::updateListing()
|
|||
// Now add the directory entries
|
||||
for(unsigned int idx = 0; idx < content.size(); idx++)
|
||||
{
|
||||
string name = content[idx].getDisplayName();
|
||||
string name = content[idx].getName();
|
||||
bool isDir = content[idx].isDirectory();
|
||||
if(isDir)
|
||||
name = " [" + name + "]";
|
||||
|
|
|
@ -401,18 +401,15 @@ void LauncherDialog::loadDirListing()
|
|||
bool domatch = myPattern && myPattern->getEditString() != "";
|
||||
for(unsigned int idx = 0; idx < files.size(); idx++)
|
||||
{
|
||||
string name = files[idx].getDisplayName();
|
||||
bool isDir = files[idx].isDirectory();
|
||||
const string& name = isDir ? (" [" + files[idx].getName() + "]")
|
||||
: files[idx].getName();
|
||||
|
||||
// Honour the filtering settings
|
||||
// Showing only certain ROM extensions is determined by the extension
|
||||
// that we want - if there are no extensions, it implies show all files
|
||||
// In this way, showing all files is on the 'fast code path'
|
||||
if(isDir)
|
||||
{
|
||||
name = " [" + name + "]";
|
||||
}
|
||||
else if(myRomExts.size() > 0)
|
||||
if(!isDir && myRomExts.size() > 0)
|
||||
{
|
||||
// Skip over those names we've filtered out
|
||||
if(!LauncherFilterDialog::isValidRomName(name, myRomExts))
|
||||
|
|
|
@ -116,8 +116,9 @@ void LoggerDialog::saveConfig()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void LoggerDialog::saveLogFile()
|
||||
{
|
||||
string path = AbstractFilesystemNode::getAbsolutePath("stella", "~", "log");
|
||||
FilesystemNode node(path);
|
||||
ostringstream path;
|
||||
path << "~" << BSPF_PATH_SEPARATOR << "stella.log";
|
||||
FilesystemNode node(path.str());
|
||||
|
||||
ofstream out(node.getPath().c_str(), ios::out);
|
||||
if(out.is_open())
|
||||
|
|
|
@ -152,13 +152,12 @@ void RomAuditDialog::auditRoms()
|
|||
const string& name = props.get(Cartridge_Name);
|
||||
|
||||
// Only rename the file if we found a valid properties entry
|
||||
if(name != "" && name != files[idx].getDisplayName())
|
||||
if(name != "" && name != files[idx].getName())
|
||||
{
|
||||
const string& newfile = node.getPath() + name + "." + extension;
|
||||
|
||||
if(files[idx].getPath() != newfile)
|
||||
if(AbstractFilesystemNode::renameFile(files[idx].getPath(), newfile))
|
||||
renamed++;
|
||||
if(files[idx].getPath() != newfile && files[idx].rename(newfile))
|
||||
renamed++;
|
||||
}
|
||||
else
|
||||
notfound++;
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#ifndef MAXPATHLEN // No MAXPATHLEN, as happens on Hurd
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implementation of the Stella file system API based on POSIX (for Linux and OSX)
|
||||
*
|
||||
|
@ -58,10 +62,9 @@ class POSIXFilesystemNode : public AbstractFilesystemNode
|
|||
* @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 = true);
|
||||
|
||||
bool exists() const { return access(_path.c_str(), F_OK) == 0; }
|
||||
const string& getDisplayName() const { return _displayName; }
|
||||
const string& getName() const { return _displayName; }
|
||||
const string& getPath() const { return _path; }
|
||||
string getRelativePath() const;
|
||||
|
@ -69,6 +72,8 @@ class POSIXFilesystemNode : public AbstractFilesystemNode
|
|||
bool isFile() const { return _isFile; }
|
||||
bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
|
||||
bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
|
||||
bool makeDir();
|
||||
bool rename(const string& newfile);
|
||||
|
||||
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
|
||||
AbstractFilesystemNode* getParent() const;
|
||||
|
@ -149,22 +154,14 @@ POSIXFilesystemNode::POSIXFilesystemNode(const string& p, bool verify)
|
|||
if(_path[0] == '~')
|
||||
{
|
||||
const char* home = getenv("HOME");
|
||||
#ifdef MAXPATHLEN
|
||||
if (home != NULL && strlen(home) < MAXPATHLEN)
|
||||
#else // No MAXPATHLEN, as happens on Hurd
|
||||
if (home != NULL)
|
||||
#endif
|
||||
{
|
||||
_path.replace(0, 1, home);
|
||||
}
|
||||
}
|
||||
|
||||
// Get absolute path
|
||||
#ifdef MAXPATHLEN
|
||||
char buf[MAXPATHLEN];
|
||||
#else // No MAXPATHLEN, as happens on Hurd
|
||||
char buf[1024];
|
||||
#endif
|
||||
if(realpath(_path.c_str(), buf))
|
||||
_path = buf;
|
||||
|
||||
|
@ -283,6 +280,54 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList& myList, ListMode mode,
|
|||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool POSIXFilesystemNode::makeDir()
|
||||
{
|
||||
if(mkdir(_path.c_str(), 0777) == 0)
|
||||
{
|
||||
// Get absolute path
|
||||
char buf[MAXPATHLEN];
|
||||
if(realpath(_path.c_str(), buf))
|
||||
_path = buf;
|
||||
|
||||
_displayName = lastPathComponent(_path);
|
||||
setFlags();
|
||||
|
||||
// Add a trailing slash, if necessary
|
||||
if (_path.length() > 0 && _path[_path.length()-1] != '/')
|
||||
_path += '/';
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool POSIXFilesystemNode::rename(const string& newfile)
|
||||
{
|
||||
if(std::rename(_path.c_str(), newfile.c_str()) == 0)
|
||||
{
|
||||
_path = newfile;
|
||||
|
||||
// Get absolute path
|
||||
char buf[MAXPATHLEN];
|
||||
if(realpath(_path.c_str(), buf))
|
||||
_path = buf;
|
||||
|
||||
_displayName = lastPathComponent(_path);
|
||||
setFlags();
|
||||
|
||||
// Add a trailing slash, if necessary
|
||||
if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '/')
|
||||
_path += '/';
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* POSIXFilesystemNode::getParent() const
|
||||
{
|
||||
|
@ -292,32 +337,13 @@ AbstractFilesystemNode* POSIXFilesystemNode::getParent() const
|
|||
const char *start = _path.c_str();
|
||||
const char *end = lastPathComponent(_path);
|
||||
|
||||
return new POSIXFilesystemNode(string(start, end - start), true);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* AbstractFilesystemNode::makeRootFileNode()
|
||||
{
|
||||
return new POSIXFilesystemNode();
|
||||
return new POSIXFilesystemNode(string(start, end - start));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path)
|
||||
{
|
||||
return new POSIXFilesystemNode(path, true);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractFilesystemNode::makeDir(const string& path)
|
||||
{
|
||||
return mkdir(path.c_str(), 0777) == 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractFilesystemNode::renameFile(const string& oldfile,
|
||||
const string& newfile)
|
||||
{
|
||||
return rename(oldfile.c_str(), newfile.c_str()) == 0;
|
||||
return new POSIXFilesystemNode(path);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -69,7 +69,8 @@ static HomeFinder myHomeFinder;
|
|||
/*
|
||||
* Implementation of the Stella file system API based on Windows API.
|
||||
*
|
||||
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
|
||||
* Parts of this class are documented in the base interface class,
|
||||
* AbstractFilesystemNode.
|
||||
*/
|
||||
class WindowsFilesystemNode : public AbstractFilesystemNode
|
||||
{
|
||||
|
@ -95,7 +96,6 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
|
|||
WindowsFilesystemNode(const string& path);
|
||||
|
||||
bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
|
||||
const string& getDisplayName() const { return _displayName; }
|
||||
const string& getName() const { return _displayName; }
|
||||
const string& getPath() const { return _path; }
|
||||
string getRelativePath() const;
|
||||
|
@ -103,6 +103,8 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
|
|||
bool isFile() const { return _isFile; }
|
||||
bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
|
||||
bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
|
||||
bool makeDir();
|
||||
bool rename(const string& newfile);
|
||||
|
||||
bool getChildren(AbstractFSList& list, ListMode mode, bool hidden) const;
|
||||
AbstractFilesystemNode* getParent() const;
|
||||
|
@ -116,6 +118,12 @@ class WindowsFilesystemNode : public AbstractFilesystemNode
|
|||
bool _isValid;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Tests and sets the _isValid and _isDirectory/_isFile flags,
|
||||
* using the GetFileAttributes() function.
|
||||
*/
|
||||
virtual void setFlags();
|
||||
|
||||
/**
|
||||
* Adds a single WindowsFilesystemNode to a given list.
|
||||
* This method is used by getChildren() to populate the directory entries list.
|
||||
|
@ -169,6 +177,36 @@ const char* lastPathComponent(const string& str)
|
|||
return cur + 1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void WindowsFilesystemNode::setFlags()
|
||||
{
|
||||
// Get absolute path
|
||||
TCHAR buf[4096];
|
||||
if(GetFullPathName(_path.c_str(), 4096, buf, NULL))
|
||||
_path = buf;
|
||||
|
||||
_displayName = lastPathComponent(_path);
|
||||
|
||||
// Check whether it is a directory, and whether the file actually exists
|
||||
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
|
||||
|
||||
if (fileAttribs == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
_isDirectory = _isFile = _isValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||
_isFile = !_isDirectory;//((fileAttribs & FILE_ATTRIBUTE_NORMAL) != 0);
|
||||
_isValid = true;
|
||||
|
||||
// Add a trailing backslash, if necessary
|
||||
if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '\\')
|
||||
_path += '\\';
|
||||
}
|
||||
_isPseudoRoot = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void WindowsFilesystemNode::addFile(AbstractFSList& list, ListMode mode,
|
||||
const char* base, WIN32_FIND_DATA* find_data)
|
||||
|
@ -246,31 +284,7 @@ WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
|
|||
if(_path[0] == '~')
|
||||
_path.replace(0, 1, myHomeFinder.getHomePath());
|
||||
|
||||
// Get absolute path
|
||||
TCHAR buf[4096];
|
||||
if(GetFullPathName(_path.c_str(), 4096, buf, NULL))
|
||||
_path = buf;
|
||||
|
||||
_displayName = lastPathComponent(_path);
|
||||
|
||||
// Check whether it is a directory, and whether the file actually exists
|
||||
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
|
||||
|
||||
if (fileAttribs == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
_isDirectory = _isFile = _isValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||
_isFile = !_isDirectory;//((fileAttribs & FILE_ATTRIBUTE_NORMAL) != 0);
|
||||
_isValid = true;
|
||||
|
||||
// Add a trailing backslash, if necessary
|
||||
if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '\\')
|
||||
_path += '\\';
|
||||
}
|
||||
_isPseudoRoot = false;
|
||||
setFlags();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -345,11 +359,33 @@ bool WindowsFilesystemNode::
|
|||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool WindowsFilesystemNode::makeDir()
|
||||
{
|
||||
if(!_isPseudoRoot && CreateDirectory(_path.c_str(), NULL) != 0)
|
||||
{
|
||||
setFlags();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool WindowsFilesystemNode::rename(const string& newfile)
|
||||
{
|
||||
if(!_isPseudoRoot && MoveFile(_path.c_str(), newfile.c_str()) != 0)
|
||||
{
|
||||
setFlags();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* WindowsFilesystemNode::getParent() const
|
||||
{
|
||||
// assert(_isValid || _isPseudoRoot);
|
||||
|
||||
if (!_isValid || _isPseudoRoot)
|
||||
return 0;
|
||||
|
||||
|
@ -370,31 +406,12 @@ AbstractFilesystemNode* WindowsFilesystemNode::getParent() const
|
|||
return p;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* AbstractFilesystemNode::makeRootFileNode()
|
||||
{
|
||||
return new WindowsFilesystemNode();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AbstractFilesystemNode* AbstractFilesystemNode::makeFileNodePath(const string& path)
|
||||
{
|
||||
return new WindowsFilesystemNode(path);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractFilesystemNode::makeDir(const string& path)
|
||||
{
|
||||
return CreateDirectory(path.c_str(), NULL) != 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractFilesystemNode::renameFile(const string& oldfile,
|
||||
const string& newfile)
|
||||
{
|
||||
return MoveFile(oldfile.c_str(), newfile.c_str()) != 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string AbstractFilesystemNode::getAbsolutePath(const string& p,
|
||||
const string& startpath,
|
||||
|
|
Loading…
Reference in New Issue