diff options
Diffstat (limited to 'src/engine/shared/storage.cpp')
| -rw-r--r-- | src/engine/shared/storage.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp new file mode 100644 index 00000000..491795ad --- /dev/null +++ b/src/engine/shared/storage.cpp @@ -0,0 +1,196 @@ +// copyright (c) 2007 magnus auvinen, see licence.txt for more info +#include <base/system.h> +#include <engine/storage.h> +#include "engine.h" + +// compiled-in data-dir path +#define DATA_DIR "data" + +class CStorage : public IStorage +{ +public: + char m_aApplicationSavePath[512]; + char m_aDatadir[512]; + + CStorage() + { + m_aApplicationSavePath[0] = 0; + m_aDatadir[0] = 0; + } + + int Init(const char *pApplicationName, const char *pArgv0) + { + char aPath[1024] = {0}; + fs_storage_path(pApplicationName, m_aApplicationSavePath, sizeof(m_aApplicationSavePath)); + if(fs_makedir(m_aApplicationSavePath) == 0) + { + str_format(aPath, sizeof(aPath), "%s/screenshots", m_aApplicationSavePath); + fs_makedir(aPath); + + str_format(aPath, sizeof(aPath), "%s/maps", m_aApplicationSavePath); + fs_makedir(aPath); + + str_format(aPath, sizeof(aPath), "%s/downloadedmaps", m_aApplicationSavePath); + fs_makedir(aPath); + + str_format(aPath, sizeof(aPath), "%s/demos", m_aApplicationSavePath); + fs_makedir(aPath); + } + + return FindDatadir(pArgv0); + } + + int FindDatadir(const char *pArgv0) + { + // 1) use provided data-dir override + if(m_aDatadir[0]) + { + if(fs_is_dir(m_aDatadir)) + return 0; + else + { + dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", m_aDatadir); + return -1; + } + } + + // 2) use data-dir in PWD if present + if(fs_is_dir("data/mapres")) + { + str_copy(m_aDatadir, "data", sizeof(m_aDatadir)); + return 0; + } + + // 3) use compiled-in data-dir if present + if (fs_is_dir(DATA_DIR "/mapres")) + { + str_copy(m_aDatadir, DATA_DIR, sizeof(m_aDatadir)); + return 0; + } + + // 4) check for usable path in argv[0] + { + unsigned int Pos = ~0U; + for(unsigned i = 0; pArgv0[i]; i++) + if(pArgv0[i] == '/') + Pos = i; + + if (Pos < sizeof(m_aDatadir)) + { + char aBaseDir[sizeof(m_aDatadir)]; + str_copy(aBaseDir, pArgv0, Pos); + aBaseDir[Pos] = '\0'; + str_format(m_aDatadir, sizeof(m_aDatadir), "%s/data", aBaseDir); + + if (fs_is_dir(m_aDatadir)) + return 0; + } + } + + #if defined(CONF_FAMILY_UNIX) + // 5) check for all default locations + { + const char *aDirs[] = { + "/usr/share/teeworlds/data", + "/usr/share/games/teeworlds/data", + "/usr/local/share/teeworlds/data", + "/usr/local/share/games/teeworlds/data", + "/opt/teeworlds/data" + }; + const int DirsCount = sizeof(aDirs) / sizeof(aDirs[0]); + + int i; + for (i = 0; i < DirsCount; i++) + { + if (fs_is_dir(aDirs[i])) + { + str_copy(m_aDatadir, aDirs[i], sizeof(m_aDatadir)); + return 0; + } + } + } + #endif + + // no data-dir found + dbg_msg("engine/datadir", "warning no data directory found"); + return -1; + } + + virtual void ListDirectory(int Types, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) + { + char aBuffer[1024]; + + // list current directory + if(Types&TYPE_CURRENT) + { + fs_listdir(pPath, pfnCallback, pUser); + } + + // list users directory + if(Types&TYPE_SAVE) + { + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aApplicationSavePath, pPath); + fs_listdir(aBuffer, pfnCallback, pUser); + } + + // list datadir directory + if(Types&TYPE_DATA) + { + str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aDatadir, pPath); + fs_listdir(aBuffer, pfnCallback, pUser); + } + } + + virtual IOHANDLE OpenFile(const char *pFilename, int Flags, char *pBuffer = 0, int BufferSize = 0) + { + char aBuffer[1024]; + if(!pBuffer) + { + pBuffer = aBuffer; + BufferSize = sizeof(aBuffer); + } + + if(Flags&IOFLAG_WRITE) + { + str_format(pBuffer, BufferSize, "%s/%s", m_aApplicationSavePath, pFilename); + return io_open(pBuffer, Flags); + } + else + { + IOHANDLE Handle = 0; + + // check current directory + Handle = io_open(pFilename, Flags); + if(Handle) + return Handle; + + // check user directory + str_format(pBuffer, BufferSize, "%s/%s", m_aApplicationSavePath, pFilename); + Handle = io_open(pBuffer, Flags); + if(Handle) + return Handle; + + // check normal data directory + str_format(pBuffer, BufferSize, "%s/%s", m_aDatadir, pFilename); + Handle = io_open(pBuffer, Flags); + if(Handle) + return Handle; + } + + pBuffer[0] = 0; + return 0; + } + + static IStorage *Create(const char *pApplicationName, const char *pArgv0) + { + CStorage *p = new CStorage(); + if(p->Init(pApplicationName, pArgv0)) + { + delete p; + p = 0; + } + return p; + } +}; + +IStorage *CreateStorage(const char *pApplicationName, const char *pArgv0) { return CStorage::Create(pApplicationName, pArgv0); } |