aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2016-02-02 09:22:41 +0100
committerJohannes Schickel2016-02-02 09:22:41 +0100
commitd88b1c947717e9081f4dc440eec375064a0b6010 (patch)
tree7a8911a9d8d60bcb3c7f3da08b46f6e6c6c31160
parentbe2af0613143c2a3426be426dec1274e5d79e0a0 (diff)
parent7d014be0a2b796175a7ce40a9315603f711b2a30 (diff)
downloadscummvm-rg350-d88b1c947717e9081f4dc440eec375064a0b6010.tar.gz
scummvm-rg350-d88b1c947717e9081f4dc440eec375064a0b6010.tar.bz2
scummvm-rg350-d88b1c947717e9081f4dc440eec375064a0b6010.zip
Merge pull request #656 from lordhoto/xdg-dirs-posix
POSIX: Follow XDG Base Directory Specification for User's Files
-rw-r--r--NEWS6
-rw-r--r--README21
-rw-r--r--backends/fs/posix/posix-fs.cpp64
-rw-r--r--backends/fs/posix/posix-fs.h14
-rw-r--r--backends/platform/sdl/posix/posix.cpp121
-rw-r--r--backends/platform/sdl/posix/posix.h2
-rw-r--r--backends/saves/posix/posix-saves.cpp71
7 files changed, 237 insertions, 62 deletions
diff --git a/NEWS b/NEWS
index 018f2f9cbc..da67360550 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,12 @@ For a more comprehensive changelog of the latest experimental code, see:
SDL:
- Alt-x no longer quits ScummVM on platforms exhibiting this behavior
before. A notable example is our Windows port.
+ - On POSIX systems we now follow the XDG Base Directory Specification for
+ placement of files for users. This effectively results in new locations
+ for our configuration file, our log file, and our default savegame path.
+ We still support our previous locations. As long as they are present, we
+ continue to use them. Please refer to the README for the new locations.
+ File locations on Mac OS X are not affected by this change.
3 Skulls of the Toltecs:
- Improved AdLib music support.
diff --git a/README b/README
index a651603774..4ddc4657db 100644
--- a/README
+++ b/README
@@ -1741,7 +1741,16 @@ The platforms that currently have a different default directory are:
$HOME/Documents/ScummVM Savegames/
Other unices:
- $HOME/.scummvm/
+ We follow the XDG Base Directory Specification. This means our
+ configuration can be found in:
+ $XDG_DATA_HOME/scummvm/saves/
+
+ If XDG_DATA_HOME is not defined or empty, ~/.local/share will be used
+ as value of XDG_DATA_HOME in accordance with the specification.
+
+ If an earlier version of ScummVM was installed on your system, the
+ previous default location of '~/.scummvm' will be kept. This is detected
+ based on the presence of the path '~/.scummvm'.
Windows Vista/7:
\Users\username\AppData\Roaming\ScummVM\Saved games\
@@ -2329,7 +2338,15 @@ By default, the configuration file is saved in, and loaded from:
previous default location of '<windir>\scummvm.ini' will be kept.
Unix:
- ~/.scummvmrc
+ We follow the XDG Base Directory Specification. This means our
+ configuration can be found in:
+ $XDG_CONFIG_HOME/scummvm/scummvm.ini
+
+ If XDG_CONFIG_HOME is not defined or empty, '~/.config' will be used
+ as value for XDG_CONFIG_HOME in accordance with the specification.
+
+ If an earlier version of ScummVM was installed on your system, the
+ previous default location of '~/.scummvmrc' will be kept.
Mac OS X:
~/Library/Preferences/ScummVM Preferences
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 4baf9f14fe..1a6c4e40a5 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -38,6 +38,7 @@
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
+#include <errno.h>
#ifdef __OS2__
#define INCL_DOS
@@ -251,4 +252,67 @@ Common::WriteStream *POSIXFilesystemNode::createWriteStream() {
return StdioStream::makeFromPath(getPath(), true);
}
+namespace Posix {
+
+bool assureDirectoryExists(const Common::String &dir, const char *prefix) {
+ struct stat sb;
+
+ // Check whether the prefix exists if one is supplied.
+ if (prefix) {
+ if (stat(prefix, &sb) != 0) {
+ return false;
+ } else if (!S_ISDIR(sb.st_mode)) {
+ return false;
+ }
+ }
+
+ // Obtain absolute path.
+ Common::String path;
+ if (prefix) {
+ path = prefix;
+ path += '/';
+ path += dir;
+ } else {
+ path = dir;
+ }
+
+ path = Common::normalizePath(path, '/');
+
+ const Common::String::iterator end = path.end();
+ Common::String::iterator cur = path.begin();
+ if (*cur == '/')
+ ++cur;
+
+ do {
+ if (cur + 1 != end) {
+ if (*cur != '/') {
+ continue;
+ }
+
+ // It is kind of ugly and against the purpose of Common::String to
+ // insert 0s inside, but this is just for a local string and
+ // simplifies the code a lot.
+ *cur = '\0';
+ }
+
+ if (mkdir(path.c_str(), 0755) != 0) {
+ if (errno == EEXIST) {
+ if (stat(path.c_str(), &sb) != 0) {
+ return false;
+ } else if (!S_ISDIR(sb.st_mode)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ *cur = '/';
+ } while (cur++ != end);
+
+ return true;
+}
+
+} // End of namespace Posix
+
#endif //#if defined(POSIX)
diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h
index bd07749010..0703ac5bf5 100644
--- a/backends/fs/posix/posix-fs.h
+++ b/backends/fs/posix/posix-fs.h
@@ -81,4 +81,18 @@ private:
virtual void setFlags();
};
+namespace Posix {
+
+/**
+ * Assure that a directory path exists.
+ *
+ * @param dir The path which is required to exist.
+ * @param prefix An (optional) prefix which should not be created if non existent.
+ * prefix is prepended to dir if supplied.
+ * @return true in case the directoy exists (or was created), false otherwise.
+ */
+bool assureDirectoryExists(const Common::String &dir, const char *prefix = nullptr);
+
+} // End of namespace Posix
+
#endif
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index a711c3a96b..525c74a91a 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -33,14 +33,13 @@
#include "backends/platform/sdl/posix/posix.h"
#include "backends/saves/posix/posix-saves.h"
#include "backends/fs/posix/posix-fs-factory.h"
+#include "backends/fs/posix/posix-fs.h"
#include "backends/taskbar/unity/unity-taskbar.h"
-#include <errno.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
-
OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName)
:
_baseConfigName(baseConfigName) {
@@ -82,11 +81,54 @@ bool OSystem_POSIX::hasFeature(Feature f) {
Common::String OSystem_POSIX::getDefaultConfigFileName() {
Common::String configFile;
- // On POSIX type systems, by default we store the config file inside
- // to the HOME directory of the user.
- const char *home = getenv("HOME");
- if (home != NULL && (strlen(home) + 1 + _baseConfigName.size()) < MAXPATHLEN) {
- configFile = Common::String::format("%s/%s", home, _baseConfigName.c_str());
+ Common::String prefix;
+#ifdef MACOSX
+ prefix = getenv("HOME");
+#elif !defined(SAMSUNGTV)
+ const char *envVar;
+ // Our old configuration file path for POSIX systems was ~/.scummvmrc.
+ // If that file exists, we still use it.
+ envVar = getenv("HOME");
+ if (envVar && *envVar) {
+ configFile = envVar;
+ configFile += '/';
+ configFile += ".scummvmrc";
+
+ if (configFile.size() < MAXPATHLEN) {
+ struct stat sb;
+ if (stat(configFile.c_str(), &sb) == 0) {
+ return configFile;
+ }
+ }
+ }
+
+ // On POSIX systems we follow the XDG Base Directory Specification for
+ // where to store files. The version we based our code upon can be found
+ // over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
+ envVar = getenv("XDG_CONFIG_HOME");
+ if (!envVar || !*envVar) {
+ envVar = getenv("HOME");
+ if (!envVar) {
+ return 0;
+ }
+
+ if (Posix::assureDirectoryExists(".config", envVar)) {
+ prefix = envVar;
+ prefix += "/.config";
+ }
+ } else {
+ prefix = envVar;
+ }
+
+ if (!prefix.empty() && Posix::assureDirectoryExists("scummvm", prefix.c_str())) {
+ prefix += "/scummvm";
+ }
+#endif
+
+ if (!prefix.empty() && (prefix.size() + 1 + _baseConfigName.size()) < MAXPATHLEN) {
+ configFile = prefix;
+ configFile += '/';
+ configFile += _baseConfigName;
} else {
configFile = _baseConfigName;
}
@@ -99,58 +141,43 @@ Common::WriteStream *OSystem_POSIX::createLogFile() {
// of a failure, we know that no log file is open.
_logFilePath.clear();
- const char *home = getenv("HOME");
- if (home == NULL)
+ const char *prefix = nullptr;
+ Common::String logFile;
+#ifdef MACOSX
+ prefix = getenv("HOME");
+ if (prefix == nullptr) {
return 0;
+ }
- Common::String logFile(home);
-#ifdef MACOSX
- logFile += "/Library";
-#else
- logFile += "/.scummvm";
-#endif
-#ifdef SAMSUNGTV
+ logFile = "Library/Logs";
+#elif SAMSUNGTV
+ prefix = nullptr;
logFile = "/mtd_ram";
-#endif
-
- struct stat sb;
-
- // Check whether the dir exists
- if (stat(logFile.c_str(), &sb) == -1) {
- // The dir does not exist, or stat failed for some other reason.
- if (errno != ENOENT)
+#else
+ // On POSIX systems we follow the XDG Base Directory Specification for
+ // where to store files. The version we based our code upon can be found
+ // over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
+ prefix = getenv("XDG_CACHE_HOME");
+ if (prefix == nullptr || !*prefix) {
+ prefix = getenv("HOME");
+ if (prefix == nullptr) {
return 0;
+ }
- // If the problem was that the path pointed to nothing, try
- // to create the dir.
- if (mkdir(logFile.c_str(), 0755) != 0)
- return 0;
- } else if (!S_ISDIR(sb.st_mode)) {
- // Path is no directory. Oops
- return 0;
+ logFile = ".cache/";
}
-#ifdef MACOSX
- logFile += "/Logs";
-#else
- logFile += "/logs";
+ logFile += "scummvm/logs";
#endif
- // Check whether the dir exists
- if (stat(logFile.c_str(), &sb) == -1) {
- // The dir does not exist, or stat failed for some other reason.
- if (errno != ENOENT)
- return 0;
-
- // If the problem was that the path pointed to nothing, try
- // to create the dir.
- if (mkdir(logFile.c_str(), 0755) != 0)
- return 0;
- } else if (!S_ISDIR(sb.st_mode)) {
- // Path is no directory. Oops
+ if (!Posix::assureDirectoryExists(logFile, prefix)) {
return 0;
}
+ if (prefix) {
+ logFile = Common::String::format("%s/%s", prefix, logFile.c_str());
+ }
+
logFile += "/scummvm.log";
Common::FSNode file(logFile);
diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h
index 01a01528cd..f67515ddb3 100644
--- a/backends/platform/sdl/posix/posix.h
+++ b/backends/platform/sdl/posix/posix.h
@@ -28,7 +28,7 @@
class OSystem_POSIX : public OSystem_SDL {
public:
// Let the subclasses be able to change _baseConfigName in the constructor
- OSystem_POSIX(Common::String baseConfigName = ".scummvmrc");
+ OSystem_POSIX(Common::String baseConfigName = "scummvm.ini");
virtual ~OSystem_POSIX() {}
virtual bool hasFeature(Feature f);
diff --git a/backends/saves/posix/posix-saves.cpp b/backends/saves/posix/posix-saves.cpp
index 96828320a6..2a7b4d3e9f 100644
--- a/backends/saves/posix/posix-saves.cpp
+++ b/backends/saves/posix/posix-saves.cpp
@@ -21,16 +21,19 @@
*/
-// Enable getenv, mkdir and time.h stuff
-#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
-#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
+// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h.
+// Also with clock() in sys/time.h in some Mac OS X SDKs.
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h //On IRIX, sys/stat.h includes sys/time.h
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
+#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
#include "common/scummsys.h"
#if defined(POSIX) && !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
#include "backends/saves/posix/posix-saves.h"
+#include "backends/fs/posix/posix-fs.h"
#include "common/config-manager.h"
#include "common/savefile.h"
@@ -41,26 +44,70 @@
#include <errno.h>
#include <sys/stat.h>
-
-#ifdef MACOSX
-#define DEFAULT_SAVE_PATH "Documents/ScummVM Savegames"
-#else
-#define DEFAULT_SAVE_PATH ".scummvm"
-#endif
-
POSIXSaveFileManager::POSIXSaveFileManager() {
- // Register default savepath based on HOME
+ // Register default savepath.
#if defined(SAMSUNGTV)
ConfMan.registerDefault("savepath", "/mtd_wiselink/scummvm savegames");
#else
Common::String savePath;
+
+#if defined(MACOSX)
const char *home = getenv("HOME");
if (home && *home && strlen(home) < MAXPATHLEN) {
savePath = home;
- savePath += "/" DEFAULT_SAVE_PATH;
+ savePath += "/Documents/ScummVM Savegames";
+
ConfMan.registerDefault("savepath", savePath);
}
+#else
+ const char *envVar;
+
+ // Previously we placed our default savepath in HOME. If the directory
+ // still exists, we will use it for backwards compatability.
+ envVar = getenv("HOME");
+ if (envVar && *envVar) {
+ savePath = envVar;
+ savePath += "/.scummvm";
+
+ struct stat sb;
+ if (stat(savePath.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
+ savePath.clear();
+ }
+ }
+
+ if (savePath.empty()) {
+ Common::String prefix;
+
+ // On POSIX systems we follow the XDG Base Directory Specification for
+ // where to store files. The version we based our code upon can be found
+ // over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
+ envVar = getenv("XDG_DATA_HOME");
+ if (!envVar || !*envVar) {
+ envVar = getenv("HOME");
+ if (envVar && *envVar) {
+ prefix = envVar;
+ savePath = ".local/share/";
+ }
+ } else {
+ prefix = envVar;
+ }
+
+ // Our default save path is '$XDG_DATA_HOME/scummvm/saves'
+ savePath += "scummvm/saves";
+
+ if (!Posix::assureDirectoryExists(savePath, prefix.c_str())) {
+ savePath.clear();
+ } else {
+ savePath = prefix + '/' + savePath;
+ }
+ }
+
+ if (!savePath.empty() && savePath.size() < MAXPATHLEN) {
+ ConfMan.registerDefault("savepath", savePath);
+ }
+#endif
+
// The user can override the savepath with the SCUMMVM_SAVEPATH
// environment variable. This is weaker than a --savepath on the
// command line, but overrides the default savepath.