aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/saves/default/default-saves.cpp59
-rw-r--r--common/savefile.h44
2 files changed, 90 insertions, 13 deletions
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 2219d1c9dc..f41455be3f 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -29,6 +29,7 @@
#include "common/savefile.h"
#include "common/util.h"
#include "common/fs.h"
+#include "common/str.h"
#include "backends/saves/default/default-saves.h"
#include "backends/saves/compressed/compressed-saves.h"
@@ -120,36 +121,69 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
// Ensure that the savepath exists and is writeable. If not, generate
// an appropriate error
const char *savePath = getSavePath();
+
#if defined(UNIX) || defined(__SYMBIAN32__)
struct stat sb;
+ clearError();
// Check whether the dir exists
if (stat(savePath, &sb) == -1) {
// The dir does not exist, or stat failed for some other reason.
// If the problem was that the path pointed to nothing, try
- // to create the dir.
- if (errno == ENOENT) {
+ // to create the dir (ENOENT case).
+ switch (errno) {
+ case EACCES:
+ setError(SFM_DIR_ACCESS, Common::String("Search or write permission denied"));
+ break;
+ case ELOOP:
+ setError(SFM_DIR_LOOP, Common::String("Too many symbolic links encountered while traversing the path"));
+ break;
+ case ENAMETOOLONG:
+ setError(SFM_DIR_NAMETOOLONG, Common::String("The path name is too long"));
+ break;
+ case ENOENT:
if (mkdir(savePath, 0755) != 0) {
// mkdir could fail for various reasons: The parent dir doesn't exist,
// or is not writeable, the path could be completly bogus, etc.
warning("mkdir for '%s' failed!", savePath);
perror("mkdir");
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
+
+ switch (errno) {
+ case EACCES:
+ setError(SFM_DIR_ACCESS, Common::String("Search or write permission denied"));
+ break;
+ case EMLINK:
+ setError(SFM_DIR_LINKMAX, Common::String("The link count of the parent directory would exceed {LINK_MAX}"));
+ break;
+ case ELOOP:
+ setError(SFM_DIR_LOOP, Common::String("Too many symbolic links encountered while traversing the path"));
+ break;
+ case ENAMETOOLONG:
+ setError(SFM_DIR_NAMETOOLONG, Common::String("The path name is too long"));
+ break;
+ case ENOENT:
+ setError(SFM_DIR_NOENT, Common::String("A component of the path path does not exist, or the path is an empty string"));
+ break;
+ case ENOTDIR:
+ setError(SFM_DIR_NOTDIR, Common::String("A component of the path prefix is not a directory"));
+ break;
+ case EROFS:
+ setError(SFM_DIR_ROFS, Common::String("The parent directory resides on a read-only file system"));
+ break;
+ }
+
return 0;
}
- } else {
- // Unknown error, abort.
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
- return 0;
- }
+ break;
+ case ENOTDIR:
+ setError(SFM_DIR_NOTDIR, Common::String("A component of the path prefix is not a directory"));
+ break;
+ }
} else {
// So stat() succeeded. But is the path actually pointing to a
// directory?
if (!S_ISDIR(sb.st_mode)) {
- // TODO: Specify an error code here so that callers can
- // determine what exactly went wrong.
+ setError(SFM_DIR_NOTDIR, Common::String("The given savepath is not a directory"));
return 0;
}
}
@@ -164,6 +198,7 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
delete sf;
sf = 0;
}
+
return wrapOutSaveFile(sf);
}
diff --git a/common/savefile.h b/common/savefile.h
index fec6fc697b..7c97ea5058 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -78,8 +78,50 @@ public:
class SaveFileManager : NonCopyable {
public:
+ 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
+ };
+
+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