diff --git a/src/base/log.cpp b/src/base/log.cpp index 989238007be..20b6af5e2c0 100644 --- a/src/base/log.cpp +++ b/src/base/log.cpp @@ -549,3 +549,38 @@ void CFutureLogger::OnFilterChange() pLogger->SetFilter(m_Filter); } } + +void CMemoryLogger::Log(const CLogMessage *pMessage) +{ + if(m_pParentLogger) + { + m_pParentLogger->Log(pMessage); + } + if(m_Filter.Filters(pMessage)) + { + return; + } + const CLockScope LockScope(m_MessagesMutex); + m_vMessages.push_back(*pMessage); +} + +std::vector CMemoryLogger::Lines() +{ + const CLockScope LockScope(m_MessagesMutex); + return m_vMessages; +} + +std::string CMemoryLogger::ConcatenatedLines() +{ + const CLockScope LockScope(m_MessagesMutex); + std::string Result; + for(const CLogMessage &Message : m_vMessages) + { + if(!Result.empty()) + { + Result += '\n'; + } + Result += Message.m_aLine; + } + return Result; +} diff --git a/src/base/logger.h b/src/base/logger.h index b43d0468c06..7365ba0b492 100644 --- a/src/base/logger.h +++ b/src/base/logger.h @@ -6,6 +6,7 @@ #include #include +#include #include typedef void *IOHANDLE; @@ -247,6 +248,30 @@ class CFutureLogger : public ILogger void OnFilterChange() override; }; +/** + * @ingroup Log + * + * Logger that collects messages in memory. This is useful to collect the log + * messages for a particular operation and show them in a user interface when + * the operation failed. Use only temporarily with @link CLogScope @endlink + * or it will result in excessive memory usage. + * + * Messages are also forwarded to the parent logger if it's set, regardless + * of this logger's filter. + */ +class CMemoryLogger : public ILogger +{ + ILogger *m_pParentLogger = nullptr; + std::vector m_vMessages GUARDED_BY(m_MessagesMutex); + CLock m_MessagesMutex; + +public: + void SetParent(ILogger *pParentLogger) { m_pParentLogger = pParentLogger; } + void Log(const CLogMessage *pMessage) override REQUIRES(!m_MessagesMutex); + std::vector Lines() REQUIRES(!m_MessagesMutex); + std::string ConcatenatedLines() REQUIRES(!m_MessagesMutex); +}; + /** * @ingroup Log * diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 51f17dfdcdb..cfb29c632f0 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -4067,8 +4067,7 @@ void CClient::Con_BenchmarkQuit(IConsole::IResult *pResult, void *pUserData) void CClient::BenchmarkQuit(int Seconds, const char *pFilename) { - char aBuf[IO_MAX_PATH_LENGTH]; - m_BenchmarkFile = Storage()->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_ABSOLUTE, aBuf, sizeof(aBuf)); + m_BenchmarkFile = Storage()->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_ABSOLUTE); m_BenchmarkStopTime = time_get() + time_freq() * Seconds; } @@ -4708,7 +4707,23 @@ int main(int argc, const char **argv) delete pEngine; }); - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_CLIENT, argc, argv); + IStorage *pStorage; + { + CMemoryLogger MemoryLogger; + MemoryLogger.SetParent(log_get_scope_logger()); + { + CLogScope LogScope(&MemoryLogger); + pStorage = CreateStorage(IStorage::EInitializationType::CLIENT, argc, argv); + } + if(!pStorage) + { + log_error("client", "Failed to initialize the storage location (see details above)"); + std::string Message = "Failed to initialize the storage location. See details below.\n\n" + MemoryLogger.ConcatenatedLines(); + pClient->ShowMessageBox("Storage Error", Message.c_str()); + PerformAllCleanup(); + return -1; + } + } pKernel->RegisterInterface(pStorage); pFutureAssertionLogger->Set(CreateAssertionLogger(pStorage, GAME_NAME)); diff --git a/src/engine/server/main.cpp b/src/engine/server/main.cpp index 16fbc04634f..f78422b4168 100644 --- a/src/engine/server/main.cpp +++ b/src/engine/server/main.cpp @@ -120,7 +120,12 @@ int main(int argc, const char **argv) IEngine *pEngine = CreateEngine(GAME_NAME, pFutureConsoleLogger, 2 * std::thread::hardware_concurrency() + 2); pKernel->RegisterInterface(pEngine); - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_SERVER, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::SERVER, argc, argv); + if(!pStorage) + { + log_error("server", "failed to initialize storage"); + return -1; + } pKernel->RegisterInterface(pStorage); pFutureAssertionLogger->Set(CreateAssertionLogger(pStorage, GAME_NAME)); diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index 4425b0c0af5..6062f3991f3 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -19,113 +19,97 @@ class CStorage : public IStorage { -public: char m_aaStoragePaths[MAX_PATHS][IO_MAX_PATH_LENGTH]; - int m_NumPaths; - char m_aDatadir[IO_MAX_PATH_LENGTH]; - char m_aUserdir[IO_MAX_PATH_LENGTH]; - char m_aCurrentdir[IO_MAX_PATH_LENGTH]; - char m_aBinarydir[IO_MAX_PATH_LENGTH]; - - CStorage() - { - mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths)); - m_NumPaths = 0; - m_aDatadir[0] = '\0'; - m_aUserdir[0] = '\0'; - m_aCurrentdir[0] = '\0'; - m_aBinarydir[0] = '\0'; - } + int m_NumPaths = 0; + char m_aUserdir[IO_MAX_PATH_LENGTH] = ""; + char m_aDatadir[IO_MAX_PATH_LENGTH] = ""; + char m_aCurrentdir[IO_MAX_PATH_LENGTH] = ""; + char m_aBinarydir[IO_MAX_PATH_LENGTH] = ""; - int Init(int StorageType, int NumArgs, const char **ppArguments) +public: + bool Init(EInitializationType InitializationType, int NumArgs, const char **ppArguments) { -#if defined(CONF_PLATFORM_ANDROID) - // See InitAndroid in android_main.cpp for details about Android storage handling. - // The current working directory is set to the app specific external storage location - // on Android. The user data is stored within a folder "user" in the external storage. - str_copy(m_aUserdir, "user"); -#else - // get userdir - char aFallbackUserdir[IO_MAX_PATH_LENGTH]; - if(fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir))) - { - log_error("storage", "could not determine user directory"); - } - if(fs_storage_path("Teeworlds", aFallbackUserdir, sizeof(aFallbackUserdir))) - { - log_error("storage", "could not determine fallback user directory"); - } + dbg_assert(NumArgs > 0, "Expected at least one argument"); + const char *pExecutablePath = ppArguments[0]; - if((m_aUserdir[0] == '\0' || !fs_is_dir(m_aUserdir)) && aFallbackUserdir[0] != '\0' && fs_is_dir(aFallbackUserdir)) + FindUserDirectory(); + FindDataDirectory(pExecutablePath); + FindCurrentDirectory(); + FindBinaryDirectory(pExecutablePath); + + if(!LoadPathsFromFile(pExecutablePath)) { - str_copy(m_aUserdir, aFallbackUserdir); + return false; } -#endif - - // get datadir - FindDatadir(ppArguments[0]); - // get binarydir - FindBinarydir(ppArguments[0]); - - // get currentdir - if(!fs_getcwd(m_aCurrentdir, sizeof(m_aCurrentdir))) + if(!m_NumPaths) { - log_error("storage", "could not determine current directory"); + if(!AddDefaultPaths()) + { + return false; + } } - // load paths from storage.cfg - LoadPaths(ppArguments[0]); - - if(!m_NumPaths) + if(InitializationType == EInitializationType::BASIC) { - dbg_msg("storage", "using standard paths"); - AddDefaultPaths(); + return true; } - // add save directories - if(StorageType != STORAGETYPE_BASIC && m_NumPaths && (!m_aaStoragePaths[TYPE_SAVE][0] || fs_makedir_rec_for(m_aaStoragePaths[TYPE_SAVE]) || !fs_makedir(m_aaStoragePaths[TYPE_SAVE]))) + if(m_aaStoragePaths[TYPE_SAVE][0] != '\0') { - if(StorageType == STORAGETYPE_CLIENT) + if(fs_makedir_rec_for(m_aaStoragePaths[TYPE_SAVE]) != 0 || + fs_makedir(m_aaStoragePaths[TYPE_SAVE]) != 0) { - CreateFolder("screenshots", TYPE_SAVE); - CreateFolder("screenshots/auto", TYPE_SAVE); - CreateFolder("screenshots/auto/stats", TYPE_SAVE); - CreateFolder("maps", TYPE_SAVE); - CreateFolder("maps/auto", TYPE_SAVE); - CreateFolder("mapres", TYPE_SAVE); - CreateFolder("downloadedmaps", TYPE_SAVE); - CreateFolder("skins", TYPE_SAVE); - CreateFolder("skins7", TYPE_SAVE); - CreateFolder("downloadedskins", TYPE_SAVE); - CreateFolder("themes", TYPE_SAVE); - CreateFolder("communityicons", TYPE_SAVE); - CreateFolder("assets", TYPE_SAVE); - CreateFolder("assets/emoticons", TYPE_SAVE); - CreateFolder("assets/entities", TYPE_SAVE); - CreateFolder("assets/game", TYPE_SAVE); - CreateFolder("assets/particles", TYPE_SAVE); - CreateFolder("assets/hud", TYPE_SAVE); - CreateFolder("assets/extras", TYPE_SAVE); + log_error("storage", "failed to create the user directory"); + return false; + } + } + + bool Success = true; + if(InitializationType == EInitializationType::CLIENT) + { + Success &= CreateFolder("screenshots", TYPE_SAVE); + Success &= CreateFolder("screenshots/auto", TYPE_SAVE); + Success &= CreateFolder("screenshots/auto/stats", TYPE_SAVE); + Success &= CreateFolder("maps", TYPE_SAVE); + Success &= CreateFolder("maps/auto", TYPE_SAVE); + Success &= CreateFolder("mapres", TYPE_SAVE); + Success &= CreateFolder("downloadedmaps", TYPE_SAVE); + Success &= CreateFolder("skins", TYPE_SAVE); + Success &= CreateFolder("skins7", TYPE_SAVE); + Success &= CreateFolder("downloadedskins", TYPE_SAVE); + Success &= CreateFolder("themes", TYPE_SAVE); + Success &= CreateFolder("communityicons", TYPE_SAVE); + Success &= CreateFolder("assets", TYPE_SAVE); + Success &= CreateFolder("assets/emoticons", TYPE_SAVE); + Success &= CreateFolder("assets/entities", TYPE_SAVE); + Success &= CreateFolder("assets/game", TYPE_SAVE); + Success &= CreateFolder("assets/particles", TYPE_SAVE); + Success &= CreateFolder("assets/hud", TYPE_SAVE); + Success &= CreateFolder("assets/extras", TYPE_SAVE); #if defined(CONF_VIDEORECORDER) - CreateFolder("videos", TYPE_SAVE); + Success &= CreateFolder("videos", TYPE_SAVE); #endif - } - CreateFolder("dumps", TYPE_SAVE); - CreateFolder("demos", TYPE_SAVE); - CreateFolder("demos/auto", TYPE_SAVE); - CreateFolder("demos/auto/race", TYPE_SAVE); - CreateFolder("demos/auto/server", TYPE_SAVE); - CreateFolder("demos/replays", TYPE_SAVE); - CreateFolder("editor", TYPE_SAVE); - CreateFolder("ghosts", TYPE_SAVE); - CreateFolder("teehistorian", TYPE_SAVE); + } + Success &= CreateFolder("dumps", TYPE_SAVE); + Success &= CreateFolder("demos", TYPE_SAVE); + Success &= CreateFolder("demos/auto", TYPE_SAVE); + Success &= CreateFolder("demos/auto/race", TYPE_SAVE); + Success &= CreateFolder("demos/auto/server", TYPE_SAVE); + Success &= CreateFolder("demos/replays", TYPE_SAVE); + Success &= CreateFolder("editor", TYPE_SAVE); + Success &= CreateFolder("ghosts", TYPE_SAVE); + Success &= CreateFolder("teehistorian", TYPE_SAVE); + + if(!Success) + { + log_error("storage", "failed to create default folders in the user directory"); } - return m_NumPaths ? 0 : 1; + return Success; } - void LoadPaths(const char *pArgv0) + bool LoadPathsFromFile(const char *pArgv0) { // check current directory IOHANDLE File = io_open("storage.cfg", IOFLAG_READ); @@ -143,51 +127,58 @@ class CStorage : public IStorage str_append(aBuffer, "/storage.cfg"); File = io_open(aBuffer, IOFLAG_READ); } - - if(Pos >= IO_MAX_PATH_LENGTH || !File) - { - dbg_msg("storage", "couldn't open storage.cfg"); - return; - } } CLineReader LineReader; if(!LineReader.OpenFile(File)) { - dbg_msg("storage", "couldn't open storage.cfg"); - return; + log_error("storage", "couldn't open storage.cfg"); + return true; } while(const char *pLine = LineReader.Get()) { const char *pLineWithoutPrefix = str_startswith(pLine, "add_path "); if(pLineWithoutPrefix) { - AddPath(pLineWithoutPrefix); + if(!AddPath(pLineWithoutPrefix) && !m_NumPaths) + { + log_error("storage", "failed to add path for the user directory"); + return false; + } } } if(!m_NumPaths) - dbg_msg("storage", "no paths found in storage.cfg"); + { + log_error("storage", "no usable paths found in storage.cfg"); + } + return true; } - void AddDefaultPaths() + bool AddDefaultPaths() { - AddPath("$USERDIR"); + log_info("storage", "using standard paths"); + if(!AddPath("$USERDIR")) + { + log_error("storage", "failed to add default path for the user directory"); + return false; + } AddPath("$DATADIR"); AddPath("$CURRENTDIR"); + return true; } - void AddPath(const char *pPath) + bool AddPath(const char *pPath) { if(!pPath[0]) { log_error("storage", "cannot add empty path"); - return; + return false; } if(m_NumPaths >= MAX_PATHS) { log_error("storage", "cannot add path '%s', the maximum number of paths is %d", pPath, MAX_PATHS); - return; + return false; } if(!str_comp(pPath, "$USERDIR")) @@ -195,11 +186,13 @@ class CStorage : public IStorage if(m_aUserdir[0]) { str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserdir); - dbg_msg("storage", "added path '$USERDIR' ('%s')", m_aUserdir); + log_info("storage", "added path '$USERDIR' ('%s')", m_aUserdir); + return true; } else { log_error("storage", "cannot add path '$USERDIR' because it could not be determined"); + return false; } } else if(!str_comp(pPath, "$DATADIR")) @@ -207,37 +200,68 @@ class CStorage : public IStorage if(m_aDatadir[0]) { str_copy(m_aaStoragePaths[m_NumPaths++], m_aDatadir); - dbg_msg("storage", "added path '$DATADIR' ('%s')", m_aDatadir); + log_info("storage", "added path '$DATADIR' ('%s')", m_aDatadir); + return true; } else { log_error("storage", "cannot add path '$DATADIR' because it could not be determined"); + return false; } } else if(!str_comp(pPath, "$CURRENTDIR")) { m_aaStoragePaths[m_NumPaths++][0] = '\0'; - dbg_msg("storage", "added path '$CURRENTDIR' ('%s')", m_aCurrentdir); + log_info("storage", "added path '$CURRENTDIR' ('%s')", m_aCurrentdir); + return true; } else if(str_utf8_check(pPath)) { if(fs_is_dir(pPath)) { str_copy(m_aaStoragePaths[m_NumPaths++], pPath); - dbg_msg("storage", "added path '%s'", pPath); + log_info("storage", "added path '%s'", pPath); + return true; } else { log_error("storage", "cannot add path '%s', which is not a directory", pPath); + return false; } } else { log_error("storage", "cannot add path containing invalid UTF-8"); + return false; + } + } + + void FindUserDirectory() + { +#if defined(CONF_PLATFORM_ANDROID) + // See InitAndroid in android_main.cpp for details about Android storage handling. + // The current working directory is set to the app specific external storage location + // on Android. The user data is stored within a folder "user" in the external storage. + str_copy(m_aUserdir, "user"); +#else + char aFallbackUserdir[IO_MAX_PATH_LENGTH]; + if(fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir))) + { + log_error("storage", "could not determine user directory"); + } + if(fs_storage_path("Teeworlds", aFallbackUserdir, sizeof(aFallbackUserdir))) + { + log_error("storage", "could not determine fallback user directory"); + } + + if((m_aUserdir[0] == '\0' || !fs_is_dir(m_aUserdir)) && aFallbackUserdir[0] != '\0' && fs_is_dir(aFallbackUserdir)) + { + str_copy(m_aUserdir, aFallbackUserdir); } +#endif } - void FindDatadir(const char *pArgv0) + void FindDataDirectory(const char *pArgv0) { // 1) use data-dir in PWD if present if(fs_is_dir("data/mapres")) @@ -296,7 +320,7 @@ class CStorage : public IStorage for(const char *pDir : apDirs) { - char aBuf[128]; + char aBuf[IO_MAX_PATH_LENGTH]; str_format(aBuf, sizeof(aBuf), "%s/data/mapres", pDir); if(fs_is_dir(aBuf)) { @@ -307,10 +331,20 @@ class CStorage : public IStorage } #endif - dbg_msg("storage", "warning: no data directory found"); + log_warn("storage", "no data directory found"); + } + + bool FindCurrentDirectory() + { + if(!fs_getcwd(m_aCurrentdir, sizeof(m_aCurrentdir))) + { + log_error("storage", "could not determine current directory"); + return false; + } + return true; } - void FindBinarydir(const char *pArgv0) + void FindBinaryDirectory(const char *pArgv0) { #if defined(BINARY_DIR) str_copy(m_aBinarydir, BINARY_DIR, sizeof(m_aBinarydir)); @@ -452,64 +486,61 @@ class CStorage : public IStorage Type = fs_is_relative_path(pPath) ? TYPE_ALL : TYPE_ABSOLUTE; } - IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0) override + IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = nullptr, int BufferSize = 0) override { TranslateType(Type, pFilename); + dbg_assert((Flags & IOFLAG_WRITE) == 0 || Type == TYPE_SAVE || Type == TYPE_ABSOLUTE, "IOFLAG_WRITE only usable with TYPE_SAVE and TYPE_ABSOLUTE"); + char aBuffer[IO_MAX_PATH_LENGTH]; if(!pBuffer) { pBuffer = aBuffer; BufferSize = sizeof(aBuffer); } + pBuffer[0] = '\0'; if(Type == TYPE_ABSOLUTE) { return io_open(GetPath(TYPE_ABSOLUTE, pFilename, pBuffer, BufferSize), Flags); } + if(str_startswith(pFilename, "mapres/../skins/")) { pFilename = pFilename + 10; // just start from skins/ } - if(pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != NULL || str_find(pFilename, "..\\") != NULL + if(pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != nullptr || str_find(pFilename, "..\\") != nullptr #ifdef CONF_FAMILY_WINDOWS || (pFilename[0] && pFilename[1] == ':') #endif ) { // don't escape base directory + return nullptr; } - else if(Flags & IOFLAG_WRITE) - { - return io_open(GetPath(TYPE_SAVE, pFilename, pBuffer, BufferSize), Flags); - } - else + else if(Type == TYPE_ALL) { - if(Type == TYPE_ALL) - { - // check all available directories - for(int i = TYPE_SAVE; i < m_NumPaths; ++i) - { - IOHANDLE Handle = io_open(GetPath(i, pFilename, pBuffer, BufferSize), Flags); - if(Handle) - return Handle; - } - } - else if(Type >= TYPE_SAVE && Type < m_NumPaths) + // check all available directories + for(int i = TYPE_SAVE; i < m_NumPaths; ++i) { - // check wanted directory - IOHANDLE Handle = io_open(GetPath(Type, pFilename, pBuffer, BufferSize), Flags); + IOHANDLE Handle = io_open(GetPath(i, pFilename, pBuffer, BufferSize), Flags); if(Handle) + { return Handle; + } } - else - { - dbg_assert(false, "Type invalid"); - } + return nullptr; + } + else if(Type >= TYPE_SAVE && Type < m_NumPaths) + { + // check wanted directory + return io_open(GetPath(Type, pFilename, pBuffer, BufferSize), Flags); + } + else + { + dbg_assert(false, "Type invalid"); + return nullptr; } - - pBuffer[0] = 0; - return 0; } template @@ -764,7 +795,9 @@ class CStorage : public IStorage bool Success = !fs_remove(aBuffer); if(!Success) - dbg_msg("storage", "failed to remove: %s", aBuffer); + { + log_error("storage", "failed to remove file: %s", aBuffer); + } return Success; } @@ -777,7 +810,9 @@ class CStorage : public IStorage bool Success = !fs_removedir(aBuffer); if(!Success) - dbg_msg("storage", "failed to remove: %s", aBuffer); + { + log_error("storage", "failed to remove folder: %s", aBuffer); + } return Success; } @@ -788,7 +823,9 @@ class CStorage : public IStorage bool Success = !fs_remove(aBuffer); if(!Success) - dbg_msg("storage", "failed to remove binary: %s", aBuffer); + { + log_error("storage", "failed to remove binary file: %s", aBuffer); + } return Success; } @@ -803,7 +840,9 @@ class CStorage : public IStorage bool Success = !fs_rename(aOldBuffer, aNewBuffer); if(!Success) - dbg_msg("storage", "failed to rename: %s -> %s", aOldBuffer, aNewBuffer); + { + log_error("storage", "failed to rename file: %s -> %s", aOldBuffer, aNewBuffer); + } return Success; } @@ -816,13 +855,15 @@ class CStorage : public IStorage if(fs_makedir_rec_for(aNewBuffer) < 0) { - dbg_msg("storage", "cannot create folder for: %s", aNewBuffer); + log_error("storage", "failed to create folders for: %s", aNewBuffer); return false; } bool Success = !fs_rename(aOldBuffer, aNewBuffer); if(!Success) - dbg_msg("storage", "failed to rename: %s -> %s", aOldBuffer, aNewBuffer); + { + log_error("storage", "failed to rename binary file: %s -> %s", aOldBuffer, aNewBuffer); + } return Success; } @@ -835,7 +876,9 @@ class CStorage : public IStorage bool Success = !fs_makedir(aBuffer); if(!Success) - dbg_msg("storage", "failed to create folder: %s", aBuffer); + { + log_error("storage", "failed to create folder: %s", aBuffer); + } return Success; } @@ -869,14 +912,13 @@ class CStorage : public IStorage return pBuffer; } - static IStorage *Create(int StorageType, int NumArgs, const char **ppArguments) + static IStorage *Create(EInitializationType InitializationType, int NumArgs, const char **ppArguments) { CStorage *pStorage = new CStorage(); - if(pStorage && pStorage->Init(StorageType, NumArgs, ppArguments)) + if(!pStorage->Init(InitializationType, NumArgs, ppArguments)) { - dbg_msg("storage", "initialisation failed"); delete pStorage; - pStorage = nullptr; + return nullptr; } return pStorage; } @@ -910,32 +952,30 @@ const char *IStorage::FormatTmpPath(char *aBuf, unsigned BufSize, const char *pP return aBuf; } -IStorage *CreateStorage(int StorageType, int NumArgs, const char **ppArguments) +IStorage *CreateStorage(IStorage::EInitializationType InitializationType, int NumArgs, const char **ppArguments) { - return CStorage::Create(StorageType, NumArgs, ppArguments); + return CStorage::Create(InitializationType, NumArgs, ppArguments); } IStorage *CreateLocalStorage() { CStorage *pStorage = new CStorage(); - if(pStorage) + if(!pStorage->FindCurrentDirectory() || + !pStorage->AddPath("$CURRENTDIR")) { - if(!fs_getcwd(pStorage->m_aCurrentdir, sizeof(pStorage->m_aCurrentdir))) - { - delete pStorage; - return NULL; - } - pStorage->AddPath("$CURRENTDIR"); + delete pStorage; + return nullptr; } return pStorage; } + IStorage *CreateTempStorage(const char *pDirectory) { CStorage *pStorage = new CStorage(); - if(!pStorage) + if(!pStorage->AddPath(pDirectory)) { + delete pStorage; return nullptr; } - pStorage->AddPath(pDirectory); return pStorage; } diff --git a/src/engine/storage.h b/src/engine/storage.h index eeb146588ca..b0a5ec3aa7f 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -39,10 +39,13 @@ class IStorage : public IInterface * GetCompletePath, FileExists and FolderExists. */ TYPE_ALL_OR_ABSOLUTE = -4, + }; - STORAGETYPE_BASIC = 0, - STORAGETYPE_SERVER, - STORAGETYPE_CLIENT, + enum class EInitializationType + { + BASIC, + SERVER, + CLIENT, }; virtual int NumPaths() const = 0; @@ -73,7 +76,7 @@ class IStorage : public IInterface static const char *FormatTmpPath(char *aBuf, unsigned BufSize, const char *pPath); }; -extern IStorage *CreateStorage(int StorageType, int NumArgs, const char **ppArguments); +extern IStorage *CreateStorage(IStorage::EInitializationType InitializationType, int NumArgs, const char **ppArguments); extern IStorage *CreateLocalStorage(); extern IStorage *CreateTempStorage(const char *pDirectory); diff --git a/src/tools/dummy_map.cpp b/src/tools/dummy_map.cpp index 2c58fd9ca2e..1ecac8f428c 100644 --- a/src/tools/dummy_map.cpp +++ b/src/tools/dummy_map.cpp @@ -110,7 +110,7 @@ int main(int argc, const char **argv) { CCmdlineFix CmdlineFix(&argc, &argv); log_set_global_logger_default(); - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_SERVER, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::SERVER, argc, argv); if(!pStorage) return -1; CreateEmptyMap(pStorage); diff --git a/src/tools/map_convert_07.cpp b/src/tools/map_convert_07.cpp index b64d051dca8..84383b1d943 100644 --- a/src/tools/map_convert_07.cpp +++ b/src/tools/map_convert_07.cpp @@ -114,7 +114,7 @@ int main(int argc, const char **argv) return -1; } - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_BASIC, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::BASIC, argc, argv); if(!pStorage) { dbg_msg("map_convert_07", "error loading storage"); diff --git a/src/tools/map_optimize.cpp b/src/tools/map_optimize.cpp index bb810423336..a9fab2a7664 100644 --- a/src/tools/map_optimize.cpp +++ b/src/tools/map_optimize.cpp @@ -78,7 +78,7 @@ int main(int argc, const char **argv) CCmdlineFix CmdlineFix(&argc, &argv); log_set_global_logger_default(); - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_BASIC, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::BASIC, argc, argv); if(!pStorage || argc <= 1 || argc > 3) { dbg_msg("map_optimize", "Invalid parameters or other unknown error."); diff --git a/src/tools/map_replace_image.cpp b/src/tools/map_replace_image.cpp index 2c2ba68a89d..ede0a180a1a 100644 --- a/src/tools/map_replace_image.cpp +++ b/src/tools/map_replace_image.cpp @@ -79,7 +79,7 @@ int main(int argc, const char **argv) return -1; } - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_BASIC, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::BASIC, argc, argv); if(!pStorage) { dbg_msg("map_replace_image", "error loading storage"); diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp index cc16f16233b..b01f2c44e38 100644 --- a/src/tools/map_resave.cpp +++ b/src/tools/map_resave.cpp @@ -68,7 +68,7 @@ int main(int argc, const char **argv) return -1; } - IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_BASIC, argc, argv); + IStorage *pStorage = CreateStorage(IStorage::EInitializationType::BASIC, argc, argv); if(!pStorage) { log_error(TOOL_NAME, "Error creating basic storage");