[fs] Allow real VFS files to be replaced while open

Add a Windows share-delete file open mode and use it for cached real VFS files. Close cached references before create, move, and delete so guest-side self-update flows can rename or replace files that Eden previously opened.

Also preserve Android real VFS full paths so homebrew path derivation does not lose the original file path.
This commit is contained in:
xbzk 2026-07-27 21:54:55 -03:00
parent 8ab9521cea
commit c87f6202d3
4 changed files with 112 additions and 10 deletions

View file

@ -12,7 +12,6 @@
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/logging.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_real.h"
@ -124,6 +123,7 @@ VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, OpenMode perms
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
{
std::scoped_lock lk{list_lock};
CloseCachedFileReferenceLocked(path);
cache.erase(path);
}
@ -157,6 +157,8 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault);
{
std::scoped_lock lk{list_lock};
CloseCachedFileReferenceLocked(old_path);
CloseCachedFileReferenceLocked(new_path);
cache.erase(old_path);
cache.erase(new_path);
}
@ -170,6 +172,7 @@ bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
{
std::scoped_lock lk{list_lock};
CloseCachedFileReferenceLocked(path);
cache.erase(path);
}
return FS::RemoveFile(path);
@ -222,8 +225,8 @@ std::unique_lock<std::mutex> RealVfsFilesystem::RefreshReference(const std::stri
if (!reference.file) {
this->EvictSingleReferenceLocked();
reference.file =
FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile);
reference.file = FS::FileOpen(path, ModeFlagsToFileAccessMode(perms),
FS::FileType::BinaryFile, FS::FileShareFlag::ShareReadWriteDelete);
if (reference.file) {
num_open_files++;
}
@ -297,15 +300,50 @@ RealVfsFile::~RealVfsFile() {
base.DropReference(std::move(reference));
}
void RealVfsFilesystem::CloseCachedFileReferenceLocked(const std::string& path) {
const auto it = cache.find(path);
if (it == cache.end()) {
return;
}
const auto cached_file = it->second.lock();
if (!cached_file) {
return;
}
auto* real_file = static_cast<RealVfsFile*>(cached_file.get());
auto& reference = real_file->reference;
if (!reference || !reference->file) {
return;
}
RemoveReferenceFromListLocked(*reference);
reference->file.reset();
num_open_files--;
InsertReferenceIntoListLocked(*reference);
}
std::string RealVfsFile::GetName() const {
#ifdef __ANDROID__
if (path[0] != '/') {
if (!path.empty() && path[0] != '/') {
return FS::Android::GetFilename(path);
}
#endif
return path_components.empty() ? "" : std::string(path_components.back());
}
std::string RealVfsFile::GetFullPath() const {
#ifdef __ANDROID__
if (!path.empty() && path[0] != '/') {
auto out = path;
std::replace(out.begin(), out.end(), '\\', '/');
return out;
}
#endif
return VfsFile::GetFullPath();
}
std::size_t RealVfsFile::GetSize() const {
if (size) {
return *size;

View file

@ -63,6 +63,7 @@ private:
std::unique_lock<std::mutex> RefreshReference(const std::string& path, OpenMode perms,
FileReference& reference);
void DropReference(std::unique_ptr<FileReference>&& reference);
void CloseCachedFileReferenceLocked(const std::string& path);
private:
friend class RealVfsDirectory;
@ -85,6 +86,7 @@ public:
~RealVfsFile() override;
std::string GetName() const override;
std::string GetFullPath() const override;
std::size_t GetSize() const override;
bool Resize(std::size_t new_size) override;
VirtualDir GetContainingDirectory() const override;