diff options
author | Johannes Schickel | 2016-02-02 09:22:41 +0100 |
---|---|---|
committer | Johannes Schickel | 2016-02-02 09:22:41 +0100 |
commit | d88b1c947717e9081f4dc440eec375064a0b6010 (patch) | |
tree | 7a8911a9d8d60bcb3c7f3da08b46f6e6c6c31160 | |
parent | be2af0613143c2a3426be426dec1274e5d79e0a0 (diff) | |
parent | 7d014be0a2b796175a7ce40a9315603f711b2a30 (diff) | |
download | scummvm-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-- | NEWS | 6 | ||||
-rw-r--r-- | README | 21 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.cpp | 64 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.h | 14 | ||||
-rw-r--r-- | backends/platform/sdl/posix/posix.cpp | 121 | ||||
-rw-r--r-- | backends/platform/sdl/posix/posix.h | 2 | ||||
-rw-r--r-- | backends/saves/posix/posix-saves.cpp | 71 |
7 files changed, 237 insertions, 62 deletions
@@ -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. @@ -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. |