From c8cfd8b40b92dfde35f948372b13617db5ad07a2 Mon Sep 17 00:00:00 2001 From: janwas Date: Sat, 1 Aug 2009 19:37:38 +0000 Subject: [PATCH] # groundwork for separated data/cache etc. directories (XDG) remove path.cpp (it was based on the premise that all data files lie below binaries/data) This was SVN commit r7063. --- source/graphics/ColladaManager.cpp | 11 +- source/graphics/tests/test_MeshManager.h | 10 +- source/lib/file/archive/archive.h | 3 +- source/lib/file/archive/archive_zip.cpp | 14 +-- source/lib/file/archive/archive_zip.h | 4 +- source/lib/file/common/real_directory.cpp | 8 +- source/lib/file/common/real_directory.h | 7 +- source/lib/file/file.cpp | 7 +- source/lib/file/file.h | 6 +- source/lib/file/file_system_posix.cpp | 11 +- source/lib/file/file_system_posix.h | 7 +- source/lib/file/io/block_cache.cpp | 2 +- source/lib/file/io/block_cache.h | 4 +- source/lib/file/path.cpp | 118 ---------------------- source/lib/file/path.h | 91 ----------------- source/lib/file/vfs/vfs.cpp | 6 +- source/lib/file/vfs/vfs.h | 5 +- source/lib/file/vfs/vfs_lookup.cpp | 6 +- source/lib/file/vfs/vfs_populate.cpp | 4 +- source/lib/file/vfs/vfs_tree.cpp | 6 +- source/lib/file/vfs/vfs_tree.h | 1 + source/lib/path_util.cpp | 14 +-- source/lib/path_util.h | 2 +- source/network/NetLog.cpp | 3 +- source/ps/CLogger.cpp | 5 +- source/ps/GameSetup/GameSetup.cpp | 49 +++++---- source/ps/ProfileViewer.cpp | 2 +- source/ps/Pyrogenesis.cpp | 14 ++- source/ps/Pyrogenesis.h | 6 ++ source/ps/Util.cpp | 2 +- source/ps/XML/Xeromyces.cpp | 10 +- source/ps/XML/tests/test_Xeromyces.h | 4 - 32 files changed, 123 insertions(+), 319 deletions(-) delete mode 100644 source/lib/file/path.cpp delete mode 100644 source/lib/file/path.h diff --git a/source/graphics/ColladaManager.cpp b/source/graphics/ColladaManager.cpp index bf2b4dd3bc..1bc4d1b937 100644 --- a/source/graphics/ColladaManager.cpp +++ b/source/graphics/ColladaManager.cpp @@ -233,13 +233,16 @@ VfsPath CColladaManager::GetLoadableFilename(const CStr& sourceName, FileType ty extension += hashString; extension += extn; - // realDaePath is "mods/whatever/art/meshes/whatever.dae" - Path realDaePath; - LibError ret = g_VFS->GetRealPath(dae, realDaePath); + // realDaePath_ is "[..]/mods/whatever/art/meshes/whatever.dae" + fs::path realDaePath_; + LibError ret = g_VFS->GetRealPath(dae, realDaePath_); debug_assert(ret == INFO::OK); + char realDaeBuf[PATH_MAX]; + path_copy(realDaeBuf, realDaePath_.string().c_str()); + const char* realDaePath = strstr(realDaeBuf, "mods/"); // cachedPmdVfsPath is "cache/mods/whatever/art/meshes/whatever_{hash}.pmd" - VfsPath cachedPmdVfsPath = VfsPath("cache/") / realDaePath.string(); + VfsPath cachedPmdVfsPath = VfsPath("cache/") / realDaePath; cachedPmdVfsPath = change_extension(cachedPmdVfsPath, extension); // If it's not in the cache, we'll have to create it first diff --git a/source/graphics/tests/test_MeshManager.h b/source/graphics/tests/test_MeshManager.h index 07d54be3e3..3f21e59130 100644 --- a/source/graphics/tests/test_MeshManager.h +++ b/source/graphics/tests/test_MeshManager.h @@ -19,7 +19,6 @@ #include "lib/file/vfs/vfs.h" #include "lib/file/io/io.h" -#include "lib/file/path.h" #include "lib/file/file_system_posix.h" #include "graphics/ColladaManager.h" @@ -27,9 +26,10 @@ #include "graphics/ModelDef.h" #include "ps/CLogger.h" +#include "ps/Pyrogenesis.h" -static Path MOD_PATH("mods/_test.mesh"); -static Path CACHE_PATH("_testcache"); +static fs::path MOD_PATH(psLogPath()/"../data/mods/_test.mesh"); +static fs::path CACHE_PATH(psLogPath()/"../data/_testcache"); const char* srcDAE = "collada/sphere.dae"; const char* srcPMD = "collada/sphere.pmd"; @@ -48,8 +48,6 @@ class TestMeshManager : public CxxTest::TestSuite { // Initialise VFS: - TS_ASSERT_OK(path_SetRoot(0, "../data")); - // Set up a mod directory to work in: // Make sure the required directories doesn't exist when we start, @@ -78,8 +76,6 @@ class TestMeshManager : public CxxTest::TestSuite // fsPosix.DeleteDirectory(MOD_PATH); // fsPosix.DeleteDirectory(CACHE_PATH); - path_ResetRootDir(); - g_VFS.reset(); } diff --git a/source/lib/file/archive/archive.h b/source/lib/file/archive/archive.h index b0a0aed4f0..767c0df6c1 100644 --- a/source/lib/file/archive/archive.h +++ b/source/lib/file/archive/archive.h @@ -22,7 +22,6 @@ #ifndef INCLUDED_ARCHIVE #define INCLUDED_ARCHIVE -#include "lib/file/path.h" #include "lib/file/file_system.h" // FileInfo #include "lib/file/common/file_loader.h" #include "lib/file/vfs/vfs_path.h" @@ -84,7 +83,7 @@ struct IArchiveWriter * precisely because they aren't in archives, and the cache would * thrash anyway, so this is deemed acceptable. **/ - virtual LibError AddFile(const Path& pathname) = 0; + virtual LibError AddFile(const fs::path& pathname) = 0; }; typedef shared_ptr PIArchiveWriter; diff --git a/source/lib/file/archive/archive_zip.cpp b/source/lib/file/archive/archive_zip.cpp index 2d0c700fd6..1f5950f89e 100644 --- a/source/lib/file/archive/archive_zip.cpp +++ b/source/lib/file/archive/archive_zip.cpp @@ -371,7 +371,7 @@ private: class ArchiveReader_Zip : public IArchiveReader { public: - ArchiveReader_Zip(const Path& pathname) + ArchiveReader_Zip(const fs::path& pathname) : m_file(CreateFile_Posix()) { m_file->Open(pathname, 'r'); @@ -505,7 +505,7 @@ private: off_t m_fileSize; }; -PIArchiveReader CreateArchiveReader_Zip(const Path& archivePathname) +PIArchiveReader CreateArchiveReader_Zip(const fs::path& archivePathname) { return PIArchiveReader(new ArchiveReader_Zip(archivePathname)); } @@ -518,7 +518,7 @@ PIArchiveReader CreateArchiveReader_Zip(const Path& archivePathname) class ArchiveWriter_Zip : public IArchiveWriter { public: - ArchiveWriter_Zip(const Path& archivePathname) + ArchiveWriter_Zip(const fs::path& archivePathname) : m_file(CreateFile_Posix()), m_fileSize(0) , m_unalignedWriter(new UnalignedWriter(m_file, 0)) , m_numEntries(0) @@ -544,14 +544,14 @@ public: (void)pool_destroy(&m_cdfhPool); - const Path pathname = m_file->Pathname(); + const fs::path pathname = m_file->Pathname(); m_file.reset(); m_fileSize += off_t(cd_size+sizeof(ECDR)); truncate(pathname.external_directory_string().c_str(), m_fileSize); } - LibError AddFile(const Path& pathname) + LibError AddFile(const fs::path& pathname) { FileInfo fileInfo; RETURN_ERR(s_fileSystemPosix.GetFileInfo(pathname, &fileInfo)); @@ -629,7 +629,7 @@ public: } private: - static bool IsFileTypeIncompressible(const Path& pathname) + static bool IsFileTypeIncompressible(const fs::path& pathname) { const char* extension = path_extension(pathname.string().c_str()); @@ -658,7 +658,7 @@ private: size_t m_numEntries; }; -PIArchiveWriter CreateArchiveWriter_Zip(const Path& archivePathname) +PIArchiveWriter CreateArchiveWriter_Zip(const fs::path& archivePathname) { return PIArchiveWriter(new ArchiveWriter_Zip(archivePathname)); } diff --git a/source/lib/file/archive/archive_zip.h b/source/lib/file/archive/archive_zip.h index e20be7b33e..26f3762c5f 100644 --- a/source/lib/file/archive/archive_zip.h +++ b/source/lib/file/archive/archive_zip.h @@ -24,7 +24,7 @@ #include "archive.h" -LIB_API PIArchiveReader CreateArchiveReader_Zip(const Path& archivePathname); -LIB_API PIArchiveWriter CreateArchiveWriter_Zip(const Path& archivePathname); +LIB_API PIArchiveReader CreateArchiveReader_Zip(const fs::path& archivePathname); +LIB_API PIArchiveWriter CreateArchiveWriter_Zip(const fs::path& archivePathname); #endif // #ifndef INCLUDED_ARCHIVE_ZIP diff --git a/source/lib/file/common/real_directory.cpp b/source/lib/file/common/real_directory.cpp index d1ee99ed66..778f595a06 100644 --- a/source/lib/file/common/real_directory.cpp +++ b/source/lib/file/common/real_directory.cpp @@ -23,7 +23,7 @@ #include "lib/file/io/io.h" -RealDirectory::RealDirectory(const Path& path, size_t priority, size_t flags) +RealDirectory::RealDirectory(const fs::path& path, size_t priority, size_t flags) : m_path(path), m_priority(priority), m_flags(flags) { } @@ -53,7 +53,7 @@ RealDirectory::RealDirectory(const Path& path, size_t priority, size_t flags) LibError RealDirectory::Store(const std::string& name, const shared_ptr& fileContents, size_t size) { - const Path pathname(m_path/name); + const fs::path pathname(m_path/name); { PIFile file = CreateFile_Posix(); @@ -73,12 +73,12 @@ LibError RealDirectory::Store(const std::string& name, const shared_ptr& fil void RealDirectory::Watch() { - //m_watch = CreateWatch(Path().external_file_string().c_str()); + //m_watch = CreateWatch(fs::path().external_file_string().c_str()); } PRealDirectory CreateRealSubdirectory(const PRealDirectory& realDirectory, const std::string& subdirectoryName) { - const Path path(realDirectory->GetPath()/subdirectoryName); + const fs::path path(realDirectory->Path()/subdirectoryName); return PRealDirectory(new RealDirectory(path, realDirectory->Priority(), realDirectory->Flags())); } diff --git a/source/lib/file/common/real_directory.h b/source/lib/file/common/real_directory.h index 54400ce139..50c1fe4a88 100644 --- a/source/lib/file/common/real_directory.h +++ b/source/lib/file/common/real_directory.h @@ -19,14 +19,13 @@ #define INCLUDED_REAL_DIRECTORY #include "file_loader.h" -#include "lib/file/path.h" class RealDirectory : public IFileLoader { public: - RealDirectory(const Path& path, size_t priority, size_t flags); + RealDirectory(const fs::path& path, size_t priority, size_t flags); - const Path& GetPath() const + const fs::path& Path() const { return m_path; } @@ -57,7 +56,7 @@ private: // note: paths are relative to the root directory, so storing the // entire path instead of just the portion relative to the mount point // is not all too wasteful. - const Path m_path; + const fs::path m_path; const size_t m_priority; diff --git a/source/lib/file/file.cpp b/source/lib/file/file.cpp index e380bddd2d..120dd13e99 100644 --- a/source/lib/file/file.cpp +++ b/source/lib/file/file.cpp @@ -23,7 +23,6 @@ #include "file.h" #include "lib/file/common/file_stats.h" -#include "lib/file/path.h" ERROR_ASSOCIATE(ERR::FILE_ACCESS, "Insufficient access rights to open file", EACCES); @@ -38,7 +37,7 @@ public: Close(); } - virtual LibError Open(const Path& pathname, char mode) + virtual LibError Open(const fs::path& pathname, char mode) { debug_assert(mode == 'w' || mode == 'r'); @@ -76,7 +75,7 @@ public: } } - virtual const Path& Pathname() const + virtual const fs::path& Pathname() const { return m_pathname; } @@ -149,7 +148,7 @@ private: return INFO::OK; } - Path m_pathname; + fs::path m_pathname; char m_mode; int m_fd; }; diff --git a/source/lib/file/file.h b/source/lib/file/file.h index 05bdd19cee..c4e0bb203b 100644 --- a/source/lib/file/file.h +++ b/source/lib/file/file.h @@ -22,8 +22,6 @@ #ifndef INCLUDED_FILE #define INCLUDED_FILE -#include "path.h" - namespace ERR { const LibError FILE_ACCESS = -110300; @@ -32,11 +30,11 @@ namespace ERR struct IFile { - virtual LibError Open(const Path& pathname, char mode) = 0; + virtual LibError Open(const fs::path& pathname, char mode) = 0; virtual LibError Open(const fs::wpath& pathname, char mode) = 0; virtual void Close() = 0; - virtual const Path& Pathname() const = 0; + virtual const fs::path& Pathname() const = 0; virtual char Mode() const = 0; virtual LibError Issue(aiocb& req, off_t alignedOfs, u8* alignedBuf, size_t alignedSize) const = 0; diff --git a/source/lib/file/file_system_posix.cpp b/source/lib/file/file_system_posix.cpp index eb91efaa7f..600f8df0e5 100644 --- a/source/lib/file/file_system_posix.cpp +++ b/source/lib/file/file_system_posix.cpp @@ -28,7 +28,6 @@ #include #include "lib/path_util.h" -#include "lib/file/path.h" #include "lib/posix/posix_filesystem.h" @@ -49,7 +48,7 @@ static bool IsDummyDirectory(const char* name) return (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')); } -/*virtual*/ LibError FileSystem_Posix::GetDirectoryEntries(const Path& path, FileInfos* files, DirectoryNames* subdirectoryNames) const +/*virtual*/ LibError FileSystem_Posix::GetDirectoryEntries(const fs::path& path, FileInfos* files, DirectoryNames* subdirectoryNames) const { // open directory errno = 0; @@ -82,7 +81,7 @@ static bool IsDummyDirectory(const char* name) #else // .. call regular stat(). errno = 0; - const Path pathname(path/name); + const fs::path pathname(path/name); if(stat(pathname.external_directory_string().c_str(), &s) != 0) return LibError_from_errno(); #endif @@ -95,7 +94,7 @@ static bool IsDummyDirectory(const char* name) } -LibError FileSystem_Posix::GetFileInfo(const Path& pathname, FileInfo* pfileInfo) const +LibError FileSystem_Posix::GetFileInfo(const fs::path& pathname, FileInfo* pfileInfo) const { char osPathname[PATH_MAX]; path_copy(osPathname, pathname.external_directory_string().c_str()); @@ -117,7 +116,7 @@ LibError FileSystem_Posix::GetFileInfo(const Path& pathname, FileInfo* pfileInfo } -LibError FileSystem_Posix::DeleteDirectory(const Path& path) +LibError FileSystem_Posix::DeleteDirectory(const fs::path& path) { // note: we have to recursively empty the directory before it can // be deleted (required by Windows and POSIX rmdir()). @@ -128,7 +127,7 @@ LibError FileSystem_Posix::DeleteDirectory(const Path& path) // delete files for(size_t i = 0; i < files.size(); i++) { - const Path pathname(path/files[i].Name()); + const fs::path pathname(path/files[i].Name()); errno = 0; if(unlink(pathname.external_file_string().c_str()) != 0) return LibError_from_errno(); diff --git a/source/lib/file/file_system_posix.h b/source/lib/file/file_system_posix.h index 8a7879b794..c3a4be1d3f 100644 --- a/source/lib/file/file_system_posix.h +++ b/source/lib/file/file_system_posix.h @@ -23,7 +23,6 @@ #ifndef INCLUDED_FILE_SYSTEM_POSIX #define INCLUDED_FILE_SYSTEM_POSIX -#include "lib/file/path.h" #include "lib/file/file_system.h" // jw 2007-12-20: we'd love to replace this with boost::filesystem, @@ -33,10 +32,10 @@ struct FileSystem_Posix { - virtual LibError GetFileInfo(const Path& pathname, FileInfo* fileInfo) const; - virtual LibError GetDirectoryEntries(const Path& path, FileInfos* files, DirectoryNames* subdirectoryNames) const; + virtual LibError GetFileInfo(const fs::path& pathname, FileInfo* fileInfo) const; + virtual LibError GetDirectoryEntries(const fs::path& path, FileInfos* files, DirectoryNames* subdirectoryNames) const; - LibError DeleteDirectory(const Path& dirPath); + LibError DeleteDirectory(const fs::path& dirPath); }; typedef shared_ptr PIFileSystem_Posix; diff --git a/source/lib/file/io/block_cache.cpp b/source/lib/file/io/block_cache.cpp index bc9970d188..abf5c395db 100644 --- a/source/lib/file/io/block_cache.cpp +++ b/source/lib/file/io/block_cache.cpp @@ -37,7 +37,7 @@ BlockId::BlockId() { } -BlockId::BlockId(const Path& pathname, off_t ofs) +BlockId::BlockId(const fs::path& pathname, off_t ofs) { m_id = fnv_hash64(pathname.string().c_str(), pathname.string().length()); const size_t indexBits = 16; diff --git a/source/lib/file/io/block_cache.h b/source/lib/file/io/block_cache.h index 76d8cc0a82..15b61c8021 100644 --- a/source/lib/file/io/block_cache.h +++ b/source/lib/file/io/block_cache.h @@ -22,8 +22,6 @@ #ifndef INCLUDED_BLOCK_CACHE #define INCLUDED_BLOCK_CACHE -#include "lib/file/path.h" - /** * ID that uniquely identifies a block within a file **/ @@ -31,7 +29,7 @@ class BlockId { public: BlockId(); - BlockId(const Path& pathname, off_t ofs); + BlockId(const fs::path& pathname, off_t ofs); bool operator==(const BlockId& rhs) const; bool operator!=(const BlockId& rhs) const; diff --git a/source/lib/file/path.cpp b/source/lib/file/path.cpp deleted file mode 100644 index d46a43ec0e..0000000000 --- a/source/lib/file/path.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ - -/* - * manage paths relative to a root directory - */ - -#include "precompiled.h" -#include "path.h" - -#include - -#include "lib/posix/posix_filesystem.h" -#include "lib/sysdep/sysdep.h" // SYS_DIR_SEP -#include "lib/path_util.h" // ERR::PATH_LENGTH - - -ERROR_ASSOCIATE(ERR::PATH_ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once", -1); -ERROR_ASSOCIATE(ERR::PATH_NOT_IN_ROOT_DIR, "Accessing a file that's outside of the root dir", -1); - -bool exists(const Path& path) -{ - return fs::exists(path.external_directory_string()); -} - - - -// security check: only allow path_SetRoot once so that malicious code -// cannot circumvent the VFS checks that disallow access to anything above -// the current directory (set here). -// path_SetRoot is called early at startup, so any subsequent attempts -// are likely bogus. -// we provide for resetting this from the self-test to allow clean -// re-init of the individual tests. -static bool s_isRootPathEstablished; - -static std::string s_rootPath; - - -/*static*/ PathTraits::external_string_type PathTraits::to_external(const Path&, const PathTraits::internal_string_type& src) -{ - std::string absolutePath = s_rootPath + src; - std::replace(absolutePath.begin(), absolutePath.end(), '/', SYS_DIR_SEP); - return absolutePath; -} - -/*static*/ PathTraits::internal_string_type PathTraits::to_internal(const PathTraits::external_string_type& src) -{ - if(s_rootPath.compare(0, s_rootPath.length(), src) != 0) - DEBUG_WARN_ERR(ERR::PATH_NOT_IN_ROOT_DIR); - std::string relativePath = src.substr(s_rootPath.length(), src.length()-s_rootPath.length()); - std::replace(relativePath.begin(), relativePath.end(), SYS_DIR_SEP, '/'); - return relativePath; -} - - -LibError path_SetRoot(const char* argv0, const char* relativePath) -{ - if(s_isRootPathEstablished) - WARN_RETURN(ERR::PATH_ROOT_DIR_ALREADY_SET); - s_isRootPathEstablished = true; - - // get full path to executable - char osPathname[PATH_MAX]; - // .. first try safe, but system-dependent version - if(sys_get_executable_name(osPathname, PATH_MAX) < 0) - { - // .. failed; use argv[0] - errno = 0; - if(!realpath(argv0, osPathname)) - return LibError_from_errno(); - } - - // make sure it's valid - errno = 0; - if(access(osPathname, X_OK) < 0) - return LibError_from_errno(); - - // strip executable name - char* name = (char*)path_name_only(osPathname); - *name = '\0'; - - strcat_s(osPathname, PATH_MAX, relativePath); - - // get actual root dir - previous osPathname may include ".." - // (slight optimization, speeds up path lookup) - errno = 0; - char osRootPath[PATH_MAX]; - if(!realpath(osPathname, osRootPath)) - return LibError_from_errno(); - - s_rootPath = osRootPath; - s_rootPath.append(1, SYS_DIR_SEP); // simplifies to_external - - return INFO::OK; -} - - -void path_ResetRootDir() -{ - debug_assert(s_isRootPathEstablished); // see comment at s_isRootPathEstablished. - s_rootPath.clear(); - s_isRootPathEstablished = false; -} diff --git a/source/lib/file/path.h b/source/lib/file/path.h deleted file mode 100644 index 2f1d200254..0000000000 --- a/source/lib/file/path.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ - -/* - * manage paths relative to a root directory - */ - -// path types: - -// tag type type separator -// portable relative / -// os native absolute SYS_DIR_SEP -// vfs vfs absolute / - -// the vfs root directory is "". no ':', '\\', "." or ".." are allowed. - -#ifndef INCLUDED_PATH -#define INCLUDED_PATH - -struct PathTraits; -typedef fs::basic_path Path; - -struct PathTraits -{ - typedef std::string internal_string_type; - typedef std::string external_string_type; - - static LIB_API external_string_type to_external(const Path&, const internal_string_type& src); - static LIB_API internal_string_type to_internal(const external_string_type& src); -}; - -namespace boost -{ - namespace filesystem - { - template<> struct is_basic_path - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - } -} - -namespace ERR -{ - const LibError PATH_ROOT_DIR_ALREADY_SET = -110200; - const LibError PATH_NOT_IN_ROOT_DIR = -110201; -} - -/** - * establish the root OS directory (portable paths are relative to it) - * - * @param argv0 the value of argv[0] (used to determine the location - * of the executable in case sys_get_executable_path fails). note that - * the current directory cannot be used because it's not set when - * starting via batch file. - * @param relativePath root directory relative to the executable's directory. - * the value is considered trusted since it will typically be hard-coded. - * - * example: executable in "$install_dir/system"; desired root dir is - * "$install_dir/data" => rel_path = "../data". - * - * can only be called once unless path_ResetRootDir is called. - **/ -LIB_API LibError path_SetRoot(const char* argv0, const char* relativePath); - -/** - * reset root directory that was previously established via path_SetRoot. - * - * this function avoids the security complaint that would be raised if - * path_SetRoot is called twice; it is provided for the - * legitimate application of a self-test setUp()/tearDown(). - **/ -LIB_API void path_ResetRootDir(); - -// note: path_MakeAbsolute has been replaced by Path::external_directory_string. - -#endif // #ifndef INCLUDED_PATH diff --git a/source/lib/file/vfs/vfs.cpp b/source/lib/file/vfs/vfs.cpp index 7e05905c93..d15be6240b 100644 --- a/source/lib/file/vfs/vfs.cpp +++ b/source/lib/file/vfs/vfs.cpp @@ -39,7 +39,7 @@ public: { } - virtual LibError Mount(const VfsPath& mountPoint, const Path& path, size_t flags /* = 0 */, size_t priority /* = 0 */) + virtual LibError Mount(const VfsPath& mountPoint, const fs::path& path, size_t flags /* = 0 */, size_t priority /* = 0 */) { debug_assert(vfs_path_IsDirectory(mountPoint)); // note: mounting subdirectories is now allowed. @@ -150,12 +150,12 @@ public: m_rootDirectory.DisplayR(0); } - virtual LibError GetRealPath(const VfsPath& pathname, Path& realPathname) + virtual LibError GetRealPath(const VfsPath& pathname, fs::path& realPathname) { VfsDirectory* directory; CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0)); const PRealDirectory& realDirectory = directory->AssociatedDirectory(); - realPathname = realDirectory->GetPath() / pathname.leaf(); + realPathname = realDirectory->Path() / pathname.leaf(); return INFO::OK; } diff --git a/source/lib/file/vfs/vfs.h b/source/lib/file/vfs/vfs.h index 4fe9175339..a6a3840e60 100644 --- a/source/lib/file/vfs/vfs.h +++ b/source/lib/file/vfs/vfs.h @@ -24,7 +24,6 @@ #define INCLUDED_VFS #include "lib/file/file_system.h" // FileInfo -#include "lib/file/path.h" #include "lib/file/vfs/vfs_path.h" namespace ERR @@ -65,7 +64,7 @@ struct IVFS * if files with archive extensions are seen, their contents are added * as well. **/ - virtual LibError Mount(const VfsPath& mountPoint, const Path& path, size_t flags = 0, size_t priority = 0) = 0; + virtual LibError Mount(const VfsPath& mountPoint, const fs::path& path, size_t flags = 0, size_t priority = 0) = 0; /** * retrieve information about a file (similar to POSIX stat) @@ -128,7 +127,7 @@ struct IVFS * * this is useful when passing paths to external libraries. **/ - virtual LibError GetRealPath(const VfsPath& pathname, Path& path) = 0; + virtual LibError GetRealPath(const VfsPath& pathname, fs::path& path) = 0; }; typedef shared_ptr PIVFS; diff --git a/source/lib/file/vfs/vfs_lookup.cpp b/source/lib/file/vfs/vfs_lookup.cpp index 7eea92cffc..1f804b8e8a 100644 --- a/source/lib/file/vfs/vfs_lookup.cpp +++ b/source/lib/file/vfs/vfs_lookup.cpp @@ -64,12 +64,12 @@ LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDi if(createMissingDirectories && !subdirectory->AssociatedDirectory()) { - Path currentPath; + fs::path currentPath; if(directory->AssociatedDirectory()) // (is NULL when mounting into root) - currentPath = directory->AssociatedDirectory()->GetPath(); + currentPath = directory->AssociatedDirectory()->Path(); currentPath /= subdirectoryName; - const int ret = mkdir(currentPath.external_directory_string().c_str(), S_IRWXO|S_IRWXU|S_IRWXG); + const int ret = mkdir(currentPath.external_directory_string().c_str(), S_IRWXU); if(ret == 0) { PRealDirectory realDirectory(new RealDirectory(currentPath, 0, 0)); diff --git a/source/lib/file/vfs/vfs_populate.cpp b/source/lib/file/vfs/vfs_populate.cpp index f39503511a..30ac4d7622 100644 --- a/source/lib/file/vfs/vfs_populate.cpp +++ b/source/lib/file/vfs/vfs_populate.cpp @@ -49,7 +49,7 @@ public: { FileInfos files; files.reserve(100); DirectoryNames subdirectoryNames; subdirectoryNames.reserve(20); - RETURN_ERR(s_fileSystemPosix.GetDirectoryEntries(m_realDirectory->GetPath(), &files, &subdirectoryNames)); + RETURN_ERR(s_fileSystemPosix.GetDirectoryEntries(m_realDirectory->Path(), &files, &subdirectoryNames)); RETURN_ERR(AddFiles(files)); AddSubdirectories(subdirectoryNames); return INFO::OK; @@ -86,7 +86,7 @@ private: LibError AddFiles(const FileInfos& files) const { - const Path path(m_realDirectory->GetPath()); + const fs::path path(m_realDirectory->Path()); for(size_t i = 0; i < files.size(); i++) { diff --git a/source/lib/file/vfs/vfs_tree.cpp b/source/lib/file/vfs/vfs_tree.cpp index 173f598775..1504360588 100644 --- a/source/lib/file/vfs/vfs_tree.cpp +++ b/source/lib/file/vfs/vfs_tree.cpp @@ -65,11 +65,7 @@ void VfsFile::GenerateDescription(char* text, size_t maxChars) const char timestamp[25]; const time_t mtime = MTime(); strftime(timestamp, ARRAY_SIZE(timestamp), "%a %b %d %H:%M:%S %Y", localtime(&mtime)); - - // build format string (set width of name field so that everything - // lines up correctly) - const char* fmt = "(%c; %6d; %s)\n"; - sprintf_s(text, maxChars, fmt, m_loader->LocationCode(), Size(), timestamp); + sprintf_s(text, maxChars, "(%c; %6d; %s)\n", m_loader->LocationCode(), Size(), timestamp); } diff --git a/source/lib/file/vfs/vfs_tree.h b/source/lib/file/vfs/vfs_tree.h index 04e4005f9c..d4769037ab 100644 --- a/source/lib/file/vfs/vfs_tree.h +++ b/source/lib/file/vfs/vfs_tree.h @@ -50,6 +50,7 @@ public: bool IsSupersededBy(const VfsFile& file) const; + // store file attributes (timestamp, location, size) in a string. void GenerateDescription(char* text, size_t maxChars) const; LibError Load(const shared_ptr& buf) const; diff --git a/source/lib/path_util.cpp b/source/lib/path_util.cpp index ead59d2b80..884c15aac2 100644 --- a/source/lib/path_util.cpp +++ b/source/lib/path_util.cpp @@ -26,12 +26,12 @@ #include -ERROR_ASSOCIATE(ERR::PATH_LENGTH, "Path exceeds PATH_MAX characters", ENAMETOOLONG); -ERROR_ASSOCIATE(ERR::PATH_EMPTY, "Path is an empty string", -1); -ERROR_ASSOCIATE(ERR::PATH_NOT_RELATIVE, "Path is not relative", -1); -ERROR_ASSOCIATE(ERR::PATH_NON_PORTABLE, "Path contains OS-specific dir separator", -1); -ERROR_ASSOCIATE(ERR::PATH_NON_CANONICAL, "Path contains unsupported .. or ./", -1); -ERROR_ASSOCIATE(ERR::PATH_COMPONENT_SEPARATOR, "Path component contains dir separator", -1); +ERROR_ASSOCIATE(ERR::PATH_LENGTH, "path exceeds PATH_MAX characters", ENAMETOOLONG); +ERROR_ASSOCIATE(ERR::PATH_EMPTY, "path is an empty string", -1); +ERROR_ASSOCIATE(ERR::PATH_NOT_RELATIVE, "path is not relative", -1); +ERROR_ASSOCIATE(ERR::PATH_NON_PORTABLE, "path contains OS-specific dir separator", -1); +ERROR_ASSOCIATE(ERR::PATH_NON_CANONICAL, "path contains unsupported .. or ./", -1); +ERROR_ASSOCIATE(ERR::PATH_COMPONENT_SEPARATOR, "path component contains dir separator", -1); bool path_is_dir_sep(char c) @@ -272,7 +272,7 @@ const char* path_name_only(const char* path) if(!slash1 && !slash2) return path; - // return name, i.e. component after the last portable or platform slash + // return name, i.e. component after the last slash const char* name = std::max(slash1, slash2)+1; if(name[0] != '\0') // else path_component_validate would complain path_component_validate(name); diff --git a/source/lib/path_util.h b/source/lib/path_util.h index ee3f2d9c3d..96532d9d34 100644 --- a/source/lib/path_util.h +++ b/source/lib/path_util.h @@ -26,7 +26,7 @@ // input buffers must not exceed PATH_MAX chars, while outputs // must hold at least that much. // - unless otherwise mentioned, all functions are intended to work with -// native and portable and VFS paths. +// native and VFS paths. // when reading, both '/' and SYS_DIR_SEP are accepted; '/' is written. #ifndef INCLUDED_PATH_UTIL diff --git a/source/network/NetLog.cpp b/source/network/NetLog.cpp index edbb431358..c8cb50ef61 100644 --- a/source/network/NetLog.cpp +++ b/source/network/NetLog.cpp @@ -27,7 +27,6 @@ #include "precompiled.h" #include "NetLog.h" #include "ps/CConsole.h" -#include "lib/file/path.h" #include #include @@ -259,7 +258,7 @@ CNetLogFileSink::CNetLogFileSink( void ) CNetLogger::GetStringTime( time ); // Make relative path - Path path("../logs/net_log"); + fs::path path(psLogPath()/"net_log"); path /= time+".txt"; m_FileName = path.external_file_string(); m_Append = true; diff --git a/source/ps/CLogger.cpp b/source/ps/CLogger.cpp index 28d13189bf..18eee81adf 100644 --- a/source/ps/CLogger.cpp +++ b/source/ps/CLogger.cpp @@ -21,7 +21,6 @@ #include "CConsole.h" #include "ConfigDB.h" #include "lib/path_util.h" -#include "lib/file/path.h" #include "lib/sysdep/sysdep.h" #include @@ -55,10 +54,10 @@ const char* html_footer = ""; CLogger::CLogger() { - Path mainlogPath("../logs/mainlog.html"); + fs::path mainlogPath(psLogPath()/"mainlog.html"); m_MainLog = new std::ofstream(mainlogPath.external_file_string().c_str(), std::ofstream::out | std::ofstream::trunc); - Path interestinglogPath("../logs/interestinglog.html"); + fs::path interestinglogPath(psLogPath()/"interestinglog.html"); m_InterestingLog = new std::ofstream(interestinglogPath.external_file_string().c_str(), std::ofstream::out | std::ofstream::trunc); m_OwnsStreams = true; diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index e289fa6a8a..10d47dd75a 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -23,6 +23,7 @@ #include "lib/input.h" #include "lib/lockfree.h" #include "lib/app_hooks.h" +#include "lib/sysdep/sysdep.h" #include "lib/sysdep/cpu.h" #include "lib/sysdep/gfx.h" #include "lib/res/h_mgr.h" @@ -550,29 +551,43 @@ static size_t ChooseCacheSize() return 96*MiB; } +fs::path BinariesDir(const CStr& argv0) +{ + // get full path to executable + char pathname[PATH_MAX]; + // .. first try safe, but system-dependent version + if(sys_get_executable_name(pathname, PATH_MAX) < 0) + { + // .. failed; use argv[0] + errno = 0; + if(!realpath(argv0.c_str(), pathname)) + WARN_ERR(LibError_from_errno(false)); + } + + // make sure it's valid + errno = 0; + if(access(pathname, X_OK) < 0) + WARN_ERR(LibError_from_errno(false)); + + // strip executable name + char* name = (char*)path_name_only(pathname); + *name = '\0'; + + return fs::path(pathname); +} + static void InitVfs(const CmdLineArgs& args) { TIMER("InitVfs"); - // set root directory to "$game_dir/data". all relative file paths - // passed to file.cpp will be based from this dir. - // (we don't set current directory because other libraries may - // hijack it). - // - // "../data" is relative to the executable (in "$game_dir/system"). - // - // rationale for data/ being root: untrusted scripts must not be - // allowed to overwrite critical game (or worse, OS) files. - // the VFS prevents any accesses to files above this directory. - path_SetRoot(args.GetArg0(), "../data"); - const size_t cacheSize = ChooseCacheSize(); g_VFS = CreateVfs(cacheSize); - g_VFS->Mount("screenshots/", "screenshots"); - g_VFS->Mount("config/", "config"); - g_VFS->Mount("profiles/", "profiles"); + const fs::path binariesDir(BinariesDir(args.GetArg0())); + g_VFS->Mount("screenshots/", binariesDir/"../data/screenshots"); + g_VFS->Mount("config/", binariesDir/"../data/config"); + g_VFS->Mount("profiles/", binariesDir/"../data/profiles"); // rationale: // - this is in a separate real directory so that it can later be moved @@ -580,7 +595,7 @@ static void InitVfs(const CmdLineArgs& args) // - we mount as archivable so that all files will be added to archive. // even though we write out XMBs here, they will eventually be read, // so putting them in an archive boosts performance. - g_VFS->Mount("cache/", "cache", VFS_MOUNT_ARCHIVABLE); + g_VFS->Mount("cache/", binariesDir/"../data/cache", VFS_MOUNT_ARCHIVABLE); std::vector mods = args.GetMultiple("mod"); mods.push_back("public"); @@ -592,7 +607,7 @@ static void InitVfs(const CmdLineArgs& args) CStr path = "mods/" + mods[i]; size_t priority = i; const int flags = VFS_MOUNT_WATCH|VFS_MOUNT_ARCHIVABLE; - g_VFS->Mount("", path, flags, priority); + g_VFS->Mount("", binariesDir/"../data"/path, flags, priority); } // don't try g_VFS->Display yet: SDL_Init hasn't yet redirected stdout diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp index 3818655673..7e07d506af 100644 --- a/source/ps/ProfileViewer.cpp +++ b/source/ps/ProfileViewer.cpp @@ -428,7 +428,7 @@ void CProfileViewer::SaveToFile() { // Open the file. (It will be closed when the CProfileViewer // destructor is called.) - Path path("../logs/profile.txt"); + fs::path path(psLogPath()/"profile.txt"); m->outputStream.open(path.external_file_string().c_str(), std::ofstream::out | std::ofstream::trunc); if (m->outputStream.fail()) diff --git a/source/ps/Pyrogenesis.cpp b/source/ps/Pyrogenesis.cpp index 7730f22fa4..55c40bc7af 100644 --- a/source/ps/Pyrogenesis.cpp +++ b/source/ps/Pyrogenesis.cpp @@ -21,7 +21,6 @@ #include "ps/i18n.h" #include "lib/sysdep/sysdep.h" -#include "lib/file/path.h" #include "lib/path_util.h" #include "lib/svn_revision.h" @@ -94,12 +93,12 @@ void psBundleLogs(FILE* f) fwprintf(f, L"SVN Revision: %s\n\n", svn_revision); fwprintf(f, L"System info:\n\n"); - Path path1("../logs/system_info.txt"); + fs::path path1(psLogPath()/"system_info.txt"); AppendAsciiFile(f, path1.external_file_string().c_str()); fwprintf(f, L"\n\n====================================\n\n"); fwprintf(f, L"Main log:\n\n"); - Path path2("../logs/mainlog.html"); + fs::path path2(psLogPath()/"mainlog.html"); AppendAsciiFile(f, path2.external_file_string().c_str()); fwprintf(f, L"\n\n====================================\n\n"); } @@ -117,3 +116,12 @@ const char* psGetLogDir() ); return N_log_dir; } + + +fs::path psLogPath() +{ + char exePathname[PATH_MAX]; + (void)sys_get_executable_name(exePathname, ARRAY_SIZE(exePathname)); + path_strip_fn(exePathname); + return fs::path(exePathname)/"../logs/"; +} diff --git a/source/ps/Pyrogenesis.h b/source/ps/Pyrogenesis.h index 48ea939ed3..e9a7983eac 100644 --- a/source/ps/Pyrogenesis.h +++ b/source/ps/Pyrogenesis.h @@ -41,6 +41,12 @@ DECLARE_ERROR(PS_FAIL); extern const wchar_t* psTranslate(const wchar_t* text); extern void psTranslateFree(const wchar_t* text); extern void psBundleLogs(FILE* f); + +// (this is used by AppHooks during crash reporting, where it's useful +// not to allocate any memory.) extern const char* psGetLogDir(); +// same as psGetLogDir, but more convenient (yet doesn't cache the results). +extern fs::path psLogPath(); + #endif diff --git a/source/ps/Util.cpp b/source/ps/Util.cpp index 04d550e31e..ea9869a539 100644 --- a/source/ps/Util.cpp +++ b/source/ps/Util.cpp @@ -71,7 +71,7 @@ void WriteSystemInfo() struct utsname un; uname(&un); - Path pathname("../logs/system_info.txt"); + fs::path pathname(psLogPath()/"system_info.txt"); FILE* f = fopen(pathname.external_file_string().c_str(), "w"); if(!f) return; diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp index 9b29e416f8..095dabce58 100644 --- a/source/ps/XML/Xeromyces.cpp +++ b/source/ps/XML/Xeromyces.cpp @@ -74,13 +74,17 @@ void CXeromyces::GetXMBPath(const PIVFS& vfs, const VfsPath& xmlFilename, const // a subdirectory (which would make manually deleting all harder). // get real path of XML file (e.g. mods/official/entities/...) - Path P_XMBRealPath; - vfs->GetRealPath(xmlFilename, P_XMBRealPath); + fs::path XMBRealPath_; + vfs->GetRealPath(xmlFilename, XMBRealPath_); + char XMBRealPath[PATH_MAX]; + path_copy(XMBRealPath, XMBRealPath_.string().c_str()); // extract mod name from that + const char* modPath = strstr(XMBRealPath, "mods/"); + debug_assert(modPath != 0); char modName[PATH_MAX]; // .. NOTE: can't use %s, of course (keeps going beyond '/') - int matches = sscanf(P_XMBRealPath.string().c_str(), "mods/%[^/]", modName); + int matches = sscanf(modPath, "mods/%[^/]", modName); debug_assert(matches == 1); // build full name: cache, then mod name, XMB subdir, original XMB path diff --git a/source/ps/XML/tests/test_Xeromyces.h b/source/ps/XML/tests/test_Xeromyces.h index 97a0bf2fac..39b4a9ee56 100644 --- a/source/ps/XML/tests/test_Xeromyces.h +++ b/source/ps/XML/tests/test_Xeromyces.h @@ -19,14 +19,12 @@ #include "ps/XML/Xeromyces.h" #include "lib/file/vfs/vfs.h" -#include "lib/file/path.h" class TestXeromyces : public CxxTest::TestSuite { public: void test_paths() { - TS_ASSERT_OK(path_SetRoot(0, "../data")); PIVFS vfs = CreateVfs(20*MiB); TS_ASSERT_OK(vfs->Mount("", "mods/_test.xero")); @@ -38,8 +36,6 @@ public: CXeromyces::GetXMBPath(vfs, "a/b/test1.xml", "a/b/test1.xmb", xmbPath); TS_ASSERT_STR_EQUALS(xmbPath.string(), "cache/mods/_test.xero/xmb/a/b/test1.xmb"); - - path_ResetRootDir(); } // TODO: Should test the reading/parsing/writing code,