1
0
forked from 0ad/0ad

fix VFS real path retrieval for files mounted from multiple directories (e.g. mods)

closes #564
GetRealPath was too simplistic and just asked the directory *most
recently mounted* into the file's VFS directory for its path. the
correct solution is to ask the file's loader for its path. the archiver
IFileLoader new returns the archive's pathname as the real path.
also simplified VfsFile's interface.

This was SVN commit r8082.
This commit is contained in:
janwas 2010-09-05 21:41:45 +00:00
parent 0864ba4fb4
commit c0c8132dd4
6 changed files with 51 additions and 50 deletions

View File

@ -265,6 +265,11 @@ public:
return 'A';
}
virtual fs::wpath Path() const
{
return m_file->Pathname();
}
virtual LibError Load(const std::wstring& UNUSED(name), const shared_ptr<u8>& buf, size_t size) const
{
AdjustOffset();

View File

@ -29,6 +29,7 @@ struct IFileLoader
virtual size_t Precedence() const = 0;
virtual wchar_t LocationCode() const = 0;
virtual fs::wpath Path() const = 0;
virtual LibError Load(const std::wstring& name, const shared_ptr<u8>& buf, size_t size) const = 0;
};

View File

@ -32,11 +32,6 @@ class RealDirectory : public IFileLoader
public:
RealDirectory(const fs::wpath& path, size_t priority, size_t flags);
const fs::wpath& Path() const
{
return m_path;
}
size_t Priority() const
{
return m_priority;
@ -50,6 +45,10 @@ public:
// IFileLoader
virtual size_t Precedence() const;
virtual wchar_t LocationCode() const;
virtual fs::wpath Path() const
{
return m_path;
}
virtual LibError Load(const std::wstring& name, const shared_ptr<u8>& buf, size_t size) const;
LibError Store(const std::wstring& name, const shared_ptr<u8>& fileContents, size_t size);

View File

@ -143,12 +143,12 @@ public:
else if(size > m_cacheSize)
{
fileContents = io_Allocate(size);
RETURN_ERR(file->Load(fileContents));
RETURN_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
}
else
{
fileContents = m_fileCache.Reserve(size);
RETURN_ERR(file->Load(fileContents));
RETURN_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
m_fileCache.Add(pathname, fileContents, size);
}
}
@ -170,9 +170,9 @@ public:
virtual LibError GetRealPath(const VfsPath& pathname, fs::wpath& realPathname)
{
VfsDirectory* directory;
CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0));
realPathname = directory->AssociatedDirectory()->Path() / pathname.leaf();
VfsDirectory* directory; VfsFile* file;
CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));
realPathname = file->Loader()->Path() / pathname.leaf();
return INFO::OK;
}

View File

@ -41,37 +41,6 @@ VfsFile::VfsFile(const std::wstring& name, size_t size, time_t mtime, size_t pri
}
bool VfsFile::IsSupersededBy(const VfsFile& file) const
{
// 1) priority (override mods)
if(file.m_priority < m_priority) // lower priority
return false;
// 2) timestamp
{
const double howMuchNewer = difftime(file.MTime(), MTime());
const double threshold = 2.0; // [seconds]; resolution provided by FAT
if(howMuchNewer > threshold) // newer timestamp
return true;
if(howMuchNewer < -threshold) // older timestamp
return false;
// else: "equal" (tolerating small differences due to FAT's low
// mtime resolution)
}
// 3) precedence (efficiency of file provider)
if(file.m_loader->Precedence() < m_loader->Precedence()) // less efficient
return false;
return true;
}
LibError VfsFile::Load(const shared_ptr<u8>& buf) const
{
return m_loader->Load(Name(), buf, Size());
}
//-----------------------------------------------------------------------------
@ -81,6 +50,32 @@ VfsDirectory::VfsDirectory()
}
static bool ShouldReplaceWith(const VfsFile& previousFile, const VfsFile& newFile)
{
// 1) priority (override mods)
if(newFile.Priority() < previousFile.Priority())
return false;
// 2) timestamp
{
const double howMuchNewer = difftime(newFile.MTime(), previousFile.MTime());
const double threshold = 2.0; // FAT timestamp resolution [seconds]
if(howMuchNewer > threshold) // newer
return true;
if(howMuchNewer < -threshold) // older
return false;
// else: "equal" (tolerating small differences due to FAT's low
// mtime resolution)
}
// 3) precedence (efficiency of file provider)
if(newFile.Loader()->Precedence() < previousFile.Loader()->Precedence())
return false;
return true;
}
VfsFile* VfsDirectory::AddFile(const VfsFile& file)
{
std::pair<std::wstring, VfsFile> value = std::make_pair(file.Name(), file);
@ -89,7 +84,7 @@ VfsFile* VfsDirectory::AddFile(const VfsFile& file)
{
VfsFile& previousFile = ret.first->second;
const VfsFile& newFile = value.second;
if(previousFile.IsSupersededBy(newFile))
if(ShouldReplaceWith(previousFile, newFile))
previousFile = newFile;
}
else
@ -166,7 +161,7 @@ std::wstring FileDescription(const VfsFile& file)
wcsftime(timestamp, ARRAY_SIZE(timestamp), L"%a %b %d %H:%M:%S %Y", localtime(&mtime));
wchar_t buf[200];
swprintf_s(buf, ARRAY_SIZE(buf), L"(%c; %6lu; %ls) %ls", file.LocationCode(), (unsigned long)file.Size(), timestamp, file.Name().c_str());
swprintf_s(buf, ARRAY_SIZE(buf), L"(%c; %6lu; %ls) %ls", file.Loader()->LocationCode(), (unsigned long)file.Size(), timestamp, file.Name().c_str());
return buf;
}

View File

@ -43,11 +43,6 @@ public:
return m_name;
}
wchar_t LocationCode() const
{
return m_loader->LocationCode();
}
size_t Size() const
{
return m_size;
@ -58,9 +53,15 @@ public:
return m_mtime;
}
bool IsSupersededBy(const VfsFile& file) const;
size_t Priority() const
{
return m_priority;
}
LibError Load(const shared_ptr<u8>& buf) const;
const PIFileLoader& Loader() const
{
return m_loader;
}
private:
std::wstring m_name;