1
0
forked from 0ad/0ad

# 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.
This commit is contained in:
janwas 2009-08-01 19:37:38 +00:00
parent 7976d84a3d
commit c8cfd8b40b
32 changed files with 123 additions and 319 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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<IArchiveWriter> PIArchiveWriter;

View File

@ -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));
}

View File

@ -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

View File

@ -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<u8>& 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<u8>& 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()));
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -28,7 +28,6 @@
#include <string>
#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();

View File

@ -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<FileSystem_Posix> PIFileSystem_Posix;

View File

@ -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;

View File

@ -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;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* manage paths relative to a root directory
*/
#include "precompiled.h"
#include "path.h"
#include <string.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*
* 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<std::string, PathTraits> 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<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

View File

@ -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;
}

View File

@ -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<IVFS> PIVFS;

View File

@ -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));

View File

@ -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++)
{

View File

@ -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);
}

View File

@ -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<u8>& buf) const;

View File

@ -26,12 +26,12 @@
#include <cerrno>
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);

View File

@ -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

View File

@ -27,7 +27,6 @@
#include "precompiled.h"
#include "NetLog.h"
#include "ps/CConsole.h"
#include "lib/file/path.h"
#include <stdio.h>
#include <stdarg.h>
@ -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;

View File

@ -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 <time.h>
@ -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;

View File

@ -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<CStr> 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

View File

@ -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())

View File

@ -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/";
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,