HomeWildfire Games

Make real directory paths on the VFS predictable.

Description

Make real directory paths on the VFS predictable.

Partial revert/fix of rP13167 and rP13472.

Before this diff, it was possible for a mod containing a cache/ or a config/ folder to get written to incorrectly.
The issue is VFS can map multiple directories to one 'virtual' path, for reading mods. However, writing data is problematic: which path to choose?
The only viable solution is to use a path relative to the highest priority directory encountered in the VFS path, or write paths could be 'hijacked' by lower-priority mods.

This fixes these issues by:

  • Adding a new lookup mode ('Real-path') that explicitly picks the real path relative to the highest-priority subdirectory in the VFS Path.
  • Preventing overwriting a real directory with a lower priority one in general.
  • Revert rP8082's GetRealPath change, re-introducing the function as GetOriginalPath.

This also cleans up some duplication that led to empty mod folders in the user mod path, and cleans up loading the 'user' mod.

Note that the new 'realpath' lookup can still be somewhat complex with many mount points at various hierarchy levels, but it is at least predictable/deterministic without having to be careful about populating order.

Fixes #2553

Differential Revision: https://code.wildfiregames.com/D3217

Event Timeline

GameSetup.cpp
../../../source/ps/GameSetup/GameSetup.cpp: In function ‘void MountMods(const Paths&, const std::vector<CStr8>&)’:
../../../source/ps/GameSetup/GameSetup.cpp:414:14: warning: ‘priority’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  g_VFS->Mount(L"", modUserPath / "user", userFlags, InDevelopmentCopy() ? 0 : priority + 1);
  ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mh, also forgot to fix the windows warning I think. Will do tomorrow.

Silier raised a concern with this commit.Mar 22 2021, 8:44 PM
Silier added a subscriber: Silier.

g_VFS->Mount(L"", modUserPath / "user", userFlags, InDevelopmentCopy() ? 0 : priority + 1);

broke

pyrogenesis.exe!DirWatchManager::Add(const Path & path, std::shared_ptr<DirWatch> & dirWatch) Line 311 C++

This commit now has outstanding concerns.Mar 22 2021, 8:44 PM
wraitii removed an auditor: Silier.Mar 22 2021, 8:53 PM

Reverted for now... Gonna have to debug this somehow.

This commit no longer requires audit.Mar 22 2021, 8:53 PM

pyrogenesis.exe!DirWatchManager::Add(const Path & path, std::shared_ptr<DirWatch> & dirWatch) Line 311 C++

	pyrogenesis.exe!dir_watch_Add(const Path & path, std::shared_ptr<DirWatch> & dirWatch) Line 361	C++
	pyrogenesis.exe!RealDirectory::Watch() Line 64	C++
	pyrogenesis.exe!vfs_Populate(VfsDirectory * directory) Line 162	C++
	pyrogenesis.exe!vfs_Attach(VfsDirectory * directory, const std::shared_ptr<RealDirectory> & realDirectory) Line 188	C++
	pyrogenesis.exe!VFS::Mount(const Path & mountPoint, const Path & path, unsigned int flags, unsigned int priority) Line 70	C++
	pyrogenesis.exe!MountMods(const Paths & paths, const std::vector<CStr8,std::allocator<CStr8>> & mods) Line 414	C++
	pyrogenesis.exe!InitVfs(const CmdLineArgs & args, int flags) Line 453	C++
	pyrogenesis.exe!Init(const CmdLineArgs & args, int flags) Line 865	C++
	pyrogenesis.exe!RunGameOrAtlas(int argc, const char * * argv) Line 652	C++
	pyrogenesis.exe!SDL_main(int argc, char * * argv) Line 744	C++