diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/advancedDetector.cpp | 6 | ||||
| -rw-r--r-- | common/error.h | 47 | ||||
| -rw-r--r-- | common/file.cpp | 63 | ||||
| -rw-r--r-- | common/file.h | 5 | ||||
| -rw-r--r-- | common/fs.cpp | 210 | ||||
| -rw-r--r-- | common/fs.h | 155 | ||||
| -rw-r--r-- | common/md5.cpp | 11 | ||||
| -rw-r--r-- | common/savefile.h | 52 | 
8 files changed, 432 insertions, 117 deletions
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp index a342ed910a..f3e8671025 100644 --- a/common/advancedDetector.cpp +++ b/common/advancedDetector.cpp @@ -276,7 +276,7 @@ PluginError detectGameForEngineCreation(  	FSList fslist;  	FilesystemNode dir(ConfMan.get("path")); -	if (!dir.listDir(fslist, FilesystemNode::kListFilesOnly)) { +	if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {  		return kInvalidPathError;  	} @@ -345,7 +345,7 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p  		// Get the information of the existing files  		for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {  			if (file->isDirectory()) continue; -			tstr = file->name(); +			tstr = file->getName();  			tstr.toLowercase();  			// Strip any trailing dot @@ -364,7 +364,7 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p  			debug(3, "> %s: %s", tstr.c_str(), md5str); -			if (testFile.open(file->path())) { +			if (testFile.open(file->getPath())) {  				filesSize[tstr] = (int32)testFile.size();  				testFile.close();  			} diff --git a/common/error.h b/common/error.h new file mode 100644 index 0000000000..0ac84df5c3 --- /dev/null +++ b/common/error.h @@ -0,0 +1,47 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef COMMON_ERROR_H +#define COMMON_ERROR_H + +/** + * This file contains enums with error codes commonly used. + */ + +/** + * Errors used in the SaveFileManager class. + */ +enum SFMError { +	SFM_NO_ERROR,			//Default state, indicates no error has been recorded +	SFM_DIR_ACCESS,			//stat(), mkdir()::EACCES: Search or write permission denied +	SFM_DIR_LINKMAX,		//mkdir()::EMLINK: The link count of the parent directory would exceed {LINK_MAX} +	SFM_DIR_LOOP,			//stat(), mkdir()::ELOOP: Too many symbolic links encountered while traversing the path +	SFM_DIR_NAMETOOLONG,	//stat(), mkdir()::ENAMETOOLONG: The path name is too long +	SFM_DIR_NOENT,			//stat(), mkdir()::ENOENT: A component of the path path does not exist, or the path is an empty string +	SFM_DIR_NOTDIR,			//stat(), mkdir()::ENOTDIR: A component of the path prefix is not a directory +	SFM_DIR_ROFS			//mkdir()::EROFS: The parent directory resides on a read-only file system +}; + +#endif //COMMON_ERROR_H diff --git a/common/file.cpp b/common/file.cpp index 2eba1bcb3d..880383d220 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -28,6 +28,7 @@  #include "common/hashmap.h"  #include "common/util.h"  #include "common/hash-str.h" +#include <errno.h>  #ifdef MACOSX  #include "CoreFoundation/CoreFoundation.h" @@ -226,7 +227,7 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co  		return;  	FSList fslist; -	if (!dir.listDir(fslist, FilesystemNode::kListAll)) { +	if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {  		// Failed listing the contents of this node, so it is either not a   		// directory, or just doesn't exist at all.  		return; @@ -237,7 +238,7 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co  	// Do not add directories multiple times, unless this time they are added  	// with a bigger depth. -	const String &directory(dir.path()); +	const String &directory(dir.getPath());  	if (_defaultDirectories->contains(directory) && (*_defaultDirectories)[directory] >= level)  		return;  	(*_defaultDirectories)[directory] = level; @@ -247,13 +248,13 @@ void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, co  	for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {  		if (file->isDirectory()) { -			addDefaultDirectoryRecursive(file->path(), level - 1, prefix + file->name() + "/"); +			addDefaultDirectoryRecursive(file->getPath(), level - 1, prefix + file->getName() + "/");  		} else {  			String lfn(prefix); -			lfn += file->name(); +			lfn += file->getName();  			lfn.toLowercase();  			if (!_filesMap->contains(lfn)) { -				(*_filesMap)[lfn] = file->path(); +				(*_filesMap)[lfn] = file->getPath();  			}  		}  	} @@ -364,15 +365,21 @@ bool File::open(const String &filename, AccessMode mode) {  bool File::open(const FilesystemNode &node, AccessMode mode) {  	assert(mode == kFileReadMode || mode == kFileWriteMode); -	if (!node.isValid()) { -		warning("File::open: Trying to open an invalid FilesystemNode object"); +	if (!node.exists()) { +		warning("File::open: Trying to open a FilesystemNode which does not exist");  		return false;  	} else if (node.isDirectory()) {  		warning("File::open: Trying to open a FilesystemNode which is a directory");  		return false; -	} +	} /*else if (!node.isReadable() && mode == kFileReadMode) { +		warning("File::open: Trying to open an unreadable FilesystemNode object for reading"); +		return false; +	} else if (!node.isWritable() && mode == kFileWriteMode) { +		warning("File::open: Trying to open an unwritable FilesystemNode object for writing"); +		return false; +	}*/ -	String filename(node.name()); +	String filename(node.getName());  	if (_handle) {  		error("File::open: This file object already is opened (%s), won't open '%s'", _name.c_str(), filename.c_str()); @@ -383,7 +390,7 @@ bool File::open(const FilesystemNode &node, AccessMode mode) {  	const char *modeStr = (mode == kFileReadMode) ? "rb" : "wb"; -	_handle = fopen(node.path().c_str(), modeStr); +	_handle = fopen(node.getPath().c_str(), modeStr);  	if (_handle == NULL) {  		if (mode == kFileReadMode) @@ -402,16 +409,40 @@ bool File::open(const FilesystemNode &node, AccessMode mode) {  	return true;  } +bool File::remove(const String &filename){ +	if (remove(filename.c_str()) != 0) { +		if(errno == EACCES) +			;//TODO: read-only file +		if(errno == ENOENT) +			;//TODO: non-existent file +		 +		return false; +	} else { +		return true; +	} +} + +bool File::remove(const FilesystemNode &node){ +	if (remove(node.getPath()) != 0) { +		if(errno == EACCES) +			;//TODO: read-only file +		if(errno == ENOENT) +			;//TODO: non-existent file +				 +		return false; +	} else { +		return true; +	} +} +  bool File::exists(const String &filename) {  	// First try to find the file it via a FilesystemNode (in case an absolute  	// path was passed). But we only use this to filter out directories.  	FilesystemNode file(filename); -	// FIXME: can't use isValid() here since at the time of writing -	// FilesystemNode is to be unable to find for example files -	// added in extrapath -	if (file.isDirectory()) -		return false; - +	 +	return (!file.isDirectory() && file.exists()); +	 +	//***DEPRECATED COMMENTS BELOW, LEFT FOR DISCUSSION***  	// Next, try to locate the file by *opening* it in read mode. This has  	// multiple effects:  	// 1) It takes _filesMap and _defaultDirectories into consideration -> good diff --git a/common/file.h b/common/file.h index 3d816a6104..416ca75ec7 100644 --- a/common/file.h +++ b/common/file.h @@ -52,7 +52,7 @@ private:  	// code that accidentally copied File objects tended to break in strange  	// ways.  	File(const File &f); -	File &operator  =(const File &f); +	File &operator =(const File &f);  public:  	enum AccessMode { @@ -86,6 +86,9 @@ public:  	virtual void close(); +	virtual bool remove(const String &filename); +	virtual bool remove(const FilesystemNode &node); +	  	/**  	 * Checks if the object opened a file successfully.  	 * diff --git a/common/fs.cpp b/common/fs.cpp index c33fc42223..3e0959b232 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -23,14 +23,45 @@   */  #include "common/stdafx.h" - -#include "backends/fs/abstract-fs.h"  #include "common/util.h" +#include "backends/fs/abstract-fs.h" +#include "backends/fs/fs-factory-maker.cpp" +/* + * Simple DOS-style pattern matching function (understands * and ? like used in DOS). + * Taken from exult/files/listfiles.cc + */ +static bool matchString(const char *str, const char *pat) { +	const char *p = 0; +	const char *q = 0; +	 +	for (;;) { +		switch (*pat) { +		case '*': +			p = ++pat; +			q = str; +			break; -FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) { -	_realNode = realNode; -	_refCount = new int(1); +		default: +			if (*pat != *str) { +				if (p) { +					pat = p; +					str = ++q; +					if(!*str) +						return !*pat; +					break; +				} +				else +					return false; +			} +			// fallthrough +		case '?': +			if(!*str) +				return !*pat; +			pat++; +			str++; +		} +	}  }  FilesystemNode::FilesystemNode() { @@ -38,6 +69,11 @@ FilesystemNode::FilesystemNode() {  	_refCount = 0;  } +FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) { +	_realNode = realNode; +	_refCount = new int(1); +} +  FilesystemNode::FilesystemNode(const FilesystemNode &node) {  	_realNode = node._realNode;  	_refCount = node._refCount; @@ -46,10 +82,12 @@ FilesystemNode::FilesystemNode(const FilesystemNode &node) {  }  FilesystemNode::FilesystemNode(const Common::String &p) { +	AbstractFilesystemFactory *factory = makeFSFactory(); +	  	if (p.empty() || p == ".") -		_realNode = AbstractFilesystemNode::getCurrentDirectory(); +		_realNode = factory->makeCurrentDirectoryFileNode();  	else -		_realNode = AbstractFilesystemNode::getNodeForPath(p); +		_realNode = factory->makeFileNodePath(p);  	_refCount = new int(1);  } @@ -57,18 +95,7 @@ FilesystemNode::~FilesystemNode() {  	decRefCount();  } -void FilesystemNode::decRefCount() { -	if (_refCount) { -		assert(*_refCount > 0); -		--(*_refCount); -		if (*_refCount == 0) { -			delete _refCount; -			delete _realNode; -		} -	} -} - -FilesystemNode &FilesystemNode::operator  =(const FilesystemNode &node) { +FilesystemNode &FilesystemNode::operator= (const FilesystemNode &node) {  	if (node._refCount)  		++(*node._refCount); @@ -80,40 +107,50 @@ FilesystemNode &FilesystemNode::operator  =(const FilesystemNode &node) {  	return *this;  } -bool FilesystemNode::isValid() const { -	if (_realNode == 0) +bool FilesystemNode::operator<(const FilesystemNode& node) const +{ +	if (isDirectory() && !node.isDirectory()) +		return true; +	if (!isDirectory() && node.isDirectory())  		return false; -	return _realNode->isValid(); +	 +	return scumm_stricmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0;  } -FilesystemNode FilesystemNode::getParent() const { -	if (_realNode == 0) -		return *this; - -	AbstractFilesystemNode *node = _realNode->parent(); -	if (node == 0) { -		return *this; -	} else { -		return FilesystemNode(node); +void FilesystemNode::decRefCount() { +	if (_refCount) { +		assert(*_refCount > 0); +		--(*_refCount); +		if (*_refCount == 0) { +			delete _refCount; +			delete _realNode; +		}  	}  } +bool FilesystemNode::exists() const { +	if (_realNode == 0) +		return false; +	 +	return _realNode->exists(); +} +  FilesystemNode FilesystemNode::getChild(const Common::String &n) const {  	if (_realNode == 0)  		return *this;  	assert(_realNode->isDirectory()); -	AbstractFilesystemNode *node = _realNode->child(n); +	AbstractFilesystemNode *node = _realNode->getChild(n);  	return FilesystemNode(node);  } -bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const { +bool FilesystemNode::getChildren(FSList &fslist, ListMode mode, bool hidden) const {  	if (!_realNode || !_realNode->isDirectory())  		return false;  	AbstractFSList tmp; -	if (!_realNode->listDir(tmp, mode)) +	if (!_realNode->getChildren(tmp, mode, hidden))  		return false;  	fslist.clear(); @@ -124,33 +161,108 @@ bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const {  	return true;  } +Common::String FilesystemNode::getDisplayName() const { +	assert(_realNode); +	return _realNode->getDisplayName(); +} + +Common::String FilesystemNode::getName() const { +	assert(_realNode); +	return _realNode->getName(); +} + +FilesystemNode FilesystemNode::getParent() const { +	if (_realNode == 0) +		return *this; + +	AbstractFilesystemNode *node = _realNode->getParent(); +	if (node == 0) { +		return *this; +	} else { +		return FilesystemNode(node); +	} +} + +Common::String FilesystemNode::getPath() const { +	assert(_realNode); +	return _realNode->getPath(); +} +  bool FilesystemNode::isDirectory() const {  	if (_realNode == 0)  		return false; +	  	return _realNode->isDirectory();  } -Common::String FilesystemNode::displayName() const { -	assert(_realNode); -	return _realNode->displayName(); +bool FilesystemNode::isReadable() const { +	if (_realNode == 0) +		return false; +	 +	return _realNode->isReadable();  } -Common::String FilesystemNode::name() const { -	assert(_realNode); -	return _realNode->name(); +bool FilesystemNode::isWritable() const { +	if (_realNode == 0) +		return false; +	 +	return _realNode->isWritable();  } -Common::String FilesystemNode::path() const { -	assert(_realNode); -	return _realNode->path(); -} +bool FilesystemNode::lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const +{ +	int matches = 0; +	 +	for (FSList::iterator entry = fslist.begin(); entry != fslist.end(); ++entry) { +		if (entry->isDirectory()) { +			matches += lookupFileRec(results, *entry, filename, hidden, exhaustive); +		} +	} +	return ((matches > 0) ? true : false); +} -bool FilesystemNode::operator< (const FilesystemNode& node) const +bool FilesystemNode::lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const  { -	if (isDirectory() && !node.isDirectory()) -		return true; -	if (!isDirectory() && node.isDirectory()) +	int matches; +	 +	if (!dir.isDirectory())  		return false; -	return scumm_stricmp(displayName().c_str(), node.displayName().c_str()) < 0; +		 +	matches = lookupFileRec(results, dir, filename, hidden, exhaustive); +	 +	return ((matches > 0) ? true : false); +} + +int FilesystemNode::lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const +{ +	FSList entries; +	FSList children; +	int matches = 0; +	dir.getChildren(entries, FilesystemNode::kListAll, hidden); +	 +	//Breadth search (entries in the same level) +	for (FSList::iterator entry = entries.begin(); entry != entries.end(); ++entry) { +		if (entry->isDirectory()) { +			children.push_back(*entry); +		} else { +			//TODO: here we assume all backends implement the lastPathComponent method. It is currently static, +			//		so it might be a good idea to include it inside the backend class. This would enforce its +			//		implementation by all ports. +			if (matchString(lastPathComponent(entry->getPath()), filename.c_str())) { +				results.push_back(*entry); +				matches++; +				 +				if (!exhaustive) +					break; +			} +		} +	} +	 +	//Depth search (entries in lower levels) +	for (FSList::iterator child = children.begin(); child != children.end(); ++child) { +		matches += lookupFileRec(results, *child, filename, hidden, exhaustive); +	} +	 +	return matches;  } diff --git a/common/fs.h b/common/fs.h index 4c275b5b2a..38e5c64a10 100644 --- a/common/fs.h +++ b/common/fs.h @@ -33,7 +33,6 @@  class FilesystemNode;  class AbstractFilesystemNode; -  /**   * List of multiple file system nodes. E.g. the contents of a given directory.   * This is subclass instead of just a typedef so that we can use forward @@ -41,9 +40,8 @@ class AbstractFilesystemNode;   */  class FSList : public Common::Array<FilesystemNode> {}; -  /** - * FilesystemNode provides an abstraction for file pathes, allowing for portable + * 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:, ...).   * @@ -64,12 +62,13 @@ class FSList : public Common::Array<FilesystemNode> {};   * 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.    */  class FilesystemNode {  private: -	AbstractFilesystemNode *_realNode;  	int *_refCount; - +	AbstractFilesystemNode *_realNode;  	FilesystemNode(AbstractFilesystemNode *realNode);  public: @@ -83,9 +82,9 @@ public:  	};  	/** -	 * Create a new invalid FilesystemNode. In other words, isValid() for that -	 * node returns false, and if you try to get it's path, an assert is -	 * triggered. +	 * Create a new pathless FilesystemNode. Since there's no path associated +	 * with this node, path-related operations (i.e. exists(), isDirectory(),  +	 * getPath()) will always return false or raise an assertion.  	 */  	FilesystemNode(); @@ -113,51 +112,44 @@ public:  	/**  	 * Copy operator.  	 */ -	FilesystemNode &operator  =(const FilesystemNode &node); - +	FilesystemNode &operator= (const FilesystemNode &node); +	  	/** -	 * Checks if the FilesystemNode is valid for any usage +	 * Compare the name of this node to the name of another. Directories +	 * go before normal files.  	 */ -	bool isValid() const; +	bool operator<(const FilesystemNode& node) const;  	/** -	 * Get the parent node of this node. If this node has no parent node, -	 * then it returns a duplicate of this node. +	 * Indicates whether the object referred by this path exists in the filesystem or not. +	 *  +	 * @return bool true if the path exists, false otherwise.  	 */ -	FilesystemNode getParent() const; +	virtual bool exists() const;  	/**  	 * Fetch a child node of this node, with the given name. Only valid for -	 * directory nodes (an assertion is triggered otherwise). If no no child -	 * node with the given name exists, an invalid node is returned. +	 * directory nodes (an assertion is triggered otherwise). +	 * If no child node with the given name exists, an invalid node is returned.  	 */  	FilesystemNode getChild(const Common::String &name) const; - +	  	/**  	 * 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 succesful, false otherwise (e.g. when the directory does not exist). -	 * @todo Rename this to listChildren or getChildren.  	 */ -	virtual bool listDir(FSList &fslist, ListMode mode = kListDirectoriesOnly) const; - -	/** -	 * Is this node pointing to a directory? -	 * @todo Currently we assume that a valid node that is not a directory -	 * automatically is a file (ignoring things like symlinks). That might -	 * actually be OK... but we could still add an isFile method. Or even replace -	 * isValid and isDirectory by a getType() method that can return values like -	 * kDirNodeType, kFileNodeType, kInvalidNodeType. -	 */ -	virtual bool isDirectory() const; +	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 Common::String displayName() const; +	virtual Common::String getDisplayName() const;  	/**  	 * Return a string representation of the name of the file. This is can be @@ -167,7 +159,7 @@ public:  	 *  	 * @return the file name  	 */ -	virtual Common::String name() const; +	virtual Common::String getName() const;  	/**  	 * Return a string representation of the file which can be passed to fopen(), @@ -180,18 +172,107 @@ public:  	 *  	 * @return the 'path' represented by this filesystem node  	 */ -	virtual Common::String path() const; +	virtual Common::String getPath() const; +	 +	/** +	 * Get the parent node of this node. If this node has no parent node, +	 * then it returns a duplicate of this node. +	 */ +	FilesystemNode getParent() const;  	/** -	 * Compare the name of this node to the name of another. Directories -	 * go before normal files. +	 * 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; +	 +	/** +	 * Indicates whether the object referred by this path can be read from or not. +	 *  +	 * If the path refers to a directory, readability implies being able to read  +	 * and list the directory entries. +	 *  +	 * If the path refers to a file, readability implies being able to read the  +	 * contents of the file. +	 *  +	 * @return bool true if the object can be read, false otherwise. +	 */ +	virtual bool isReadable() const; +	 +	/** +	 * 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). +	 *  +	 * If the path refers to a file, writability implies being able to write data +	 * to the file. +	 *  +	 * @return bool true if the object can be written to, false otherwise.  	 */ -	bool operator< (const FilesystemNode& node) const; +	virtual bool isWritable() const; +	 +	/** +	 * Searches recursively for a filename inside the given directories. +	 *  +	 * For each directory in the directory list a breadth-first search is performed, +	 * that is, the current directory entries are scanned before going into subdirectories. +	 *  +	 * @param results List to put the matches in. +	 * @param fslist List of directories to search within. +	 * @param filename Name of the file to look for. +	 * @param hidden Whether to search hidden files or not. +	 * @param exhaustive Whether to continue searching after one match has been found. +	 *  +	 * @return true if matches could be found, false otherwise. +	 */ +	virtual bool lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const; +	 +	/** +	 * Searches recursively for a filename inside the given directory. +	 *  +	 * The search is performed breadth-first, that is, the current directory entries +	 * are scanned before going into subdirectories. +	 *  +	 * @param results List to put the matches in. +	 * @param FilesystemNode Directory to search within. +	 * @param filename Name of the file to look for. +	 * @param hidden Whether to search hidden files or not. +	 * @param exhaustive Whether to continue searching after one match has been found. +	 *  +	 * @return true if matches could be found, false otherwise. +	 */ +	virtual bool lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;  protected: +	/** +	 * Decreases the reference count to the FilesystemNode, and if necessary, +	 * deletes the corresponding underlying references. +	 */  	void decRefCount(); +	 +	/** +	 * Searches recursively for a filename inside the given directory. +	 *  +	 * The search is performed breadth-first, that is, the current directory entries +	 * are scanned before going into subdirectories. +	 *  +	 * @param results List to put the matches in. +	 * @param FilesystemNode Directory to search within. +	 * @param filename Name of the file to look for. +	 * @param hidden Whether to search hidden files or not. +	 * @param exhaustive Whether to continue searching after one match has been found. +	 *  +	 * @return The number of matches found. +	 */ +	int lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;  };  //} // End of namespace Common -#endif +#endif //COMMON_FS_H diff --git a/common/md5.cpp b/common/md5.cpp index a48ecb4948..32acdc5b8c 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -246,15 +246,18 @@ void md5_finish(md5_context *ctx, uint8 digest[16]) {  }  bool md5_file(const FilesystemNode &file, uint8 digest[16], uint32 length) { -	if (!file.isValid()) { -		warning("md5_file: using an invalid FilesystemNode"); +	if(!file.exists()) { +		warning("md5_file: using an inexistent FilesystemNode"); +		return false; +	} else if (!file.isReadable()) { +		warning("md5_file: using an unreadable FilesystemNode");  		return false;  	} else if (file.isDirectory()) { -		warning("md5_file: using a diretory FilesystemNode"); +		warning("md5_file: using a directory FilesystemNode");  		return false;  	} -	return md5_file(file.path().c_str(), digest, length); +	return md5_file(file.getPath().c_str(), digest, length);  }  bool md5_file(const char *name, uint8 digest[16], uint32 length) { diff --git a/common/savefile.h b/common/savefile.h index e1a54638b5..9fdd76ae15 100644 --- a/common/savefile.h +++ b/common/savefile.h @@ -30,6 +30,8 @@  #include "common/noncopyable.h"  #include "common/scummsys.h"  #include "common/stream.h" +#include "common/str.h" +#include "common/error.h"  namespace Common { @@ -75,10 +77,40 @@ public:   * returning the single SaveFileManager instances to be used.   */  class SaveFileManager : NonCopyable { - +	 +protected: +	SFMError _error; +	String _errorDesc; +	  public:  	virtual ~SaveFileManager() {} - +	 +	/** +	 * Clears the last set error code and string. +	 */ +	virtual void clearError() { _error = SFM_NO_ERROR; _errorDesc = ""; } +	 +	/** +	 * Returns the last ocurred error code. If none ocurred, returns SFM_NO_ERROR. +	 *  +	 * @return A SFMError indicating the type of the last error. +	 */ +	virtual SFMError getError() { return _error; } +	 +	/** +	 * Returns the last ocurred error description. If none ocurred, returns 0. +	 *  +	 * @return A string describing the last error. +	 */ +	virtual String getErrorDesc() { return _errorDesc; } +	 +	/** +	 * Sets the last ocurred error. +	 * @param error Code identifying the last error. +	 * @param errorDesc String describing the last error. +	 */ +	virtual void setError(SFMError error, String errorDesc) { _error = error; _errorDesc = errorDesc; } +	  	/**  	 * Open the file with name filename in the given directory for saving.  	 * @param filename	the filename @@ -94,12 +126,18 @@ public:  	virtual InSaveFile *openForLoading(const char *filename) = 0;  	/** -	 * Request a list of available savegames with a given prefix. -	 * TODO: Document this better! -	 * TODO: Or even replace it with a better API. For example, one that -	 * returns a list of strings for all present file names.  +	 * Removes the given savefile from the filesystem. +	 * @param filename Filename path pointing to the savefile. +	 * @return true if no error ocurred. false otherwise. +	 */ +	virtual bool removeSavefile(const char *filename) = 0; +	 +	/** +	 * Request a list of available savegames with a given regex. +	 * @param regex Regular expression to match. Wildcards like * or ? are available. +	 * returns a list of strings for all present file names.  	 */ -	virtual void listSavefiles(const char * /* prefix */, bool *marks, int num) = 0; +	virtual Common::StringList listSavefiles(const char *regex) = 0;  	/**  	 * Get the path to the save game directory.  | 
