IOS/FS: Make it harder to forget closing FDs
Return a FileHandle which will automatically close the FD when the handle goes out of scope. For the rare cases where this behaviour is undesirable, the FD can be released from the handle.
This commit is contained in:
parent
de15e09a4f
commit
2d8be6a77d
|
@ -49,7 +49,6 @@ static void CreateVirtualFATFilesystem(std::shared_ptr<IOS::HLE::FS::FileSystem>
|
||||||
// write the final 0 to 0 file from the second FAT to 20 MiB
|
// write the final 0 to 0 file from the second FAT to 20 MiB
|
||||||
data[CDB_SIZE - 1] = 0;
|
data[CDB_SIZE - 1] = 0;
|
||||||
fs->WriteFile(*fd, data.data(), static_cast<u32>(data.size()));
|
fs->WriteFile(*fd, data.data(), static_cast<u32>(data.size()));
|
||||||
fs->Close(*fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBoot::BootNANDTitle(const u64 title_id)
|
bool CBoot::BootNANDTitle(const u64 title_id)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "Core/IOS/FS/FileSystem.h"
|
#include "Core/IOS/FS/FileSystem.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Core/IOS/FS/HostBackend/FS.h"
|
#include "Core/IOS/FS/HostBackend/FS.h"
|
||||||
|
|
||||||
namespace IOS::HLE::FS
|
namespace IOS::HLE::FS
|
||||||
|
@ -13,6 +14,35 @@ std::unique_ptr<FileSystem> MakeFileSystem()
|
||||||
return std::make_unique<HostFileSystem>();
|
return std::make_unique<HostFileSystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle::FileHandle(FileSystem* fs, Fd fd) : m_fs{fs}, m_fd{fd}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHandle::FileHandle(FileHandle&& other) : m_fs{other.m_fs}, m_fd{other.m_fd}
|
||||||
|
{
|
||||||
|
other.m_fd.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHandle& FileHandle::operator=(FileHandle&& other)
|
||||||
|
{
|
||||||
|
if (*this != other)
|
||||||
|
*this = std::move(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHandle::~FileHandle()
|
||||||
|
{
|
||||||
|
if (m_fd && m_fs)
|
||||||
|
ASSERT(m_fs->Close(*m_fd) == FS::ResultCode::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fd FileHandle::Release()
|
||||||
|
{
|
||||||
|
const Fd fd = m_fd.value();
|
||||||
|
m_fd.reset();
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
void FileSystem::Init()
|
void FileSystem::Init()
|
||||||
{
|
{
|
||||||
if (Delete(0, 0, "/tmp") == ResultCode::Success)
|
if (Delete(0, 0, "/tmp") == ResultCode::Success)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -96,6 +97,26 @@ struct FileStatus
|
||||||
u32 size;
|
u32 size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FileSystem;
|
||||||
|
class FileHandle final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileHandle(FileSystem* fs, Fd fd);
|
||||||
|
FileHandle(FileHandle&&);
|
||||||
|
~FileHandle();
|
||||||
|
FileHandle(const FileHandle&) = delete;
|
||||||
|
FileHandle& operator=(const FileHandle&) = delete;
|
||||||
|
FileHandle& operator=(FileHandle&&);
|
||||||
|
|
||||||
|
operator Fd() const { return m_fd.value(); }
|
||||||
|
/// Release the FD so that it is not automatically closed.
|
||||||
|
Fd Release();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileSystem* m_fs;
|
||||||
|
std::optional<Fd> m_fd;
|
||||||
|
};
|
||||||
|
|
||||||
class FileSystem
|
class FileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -106,8 +127,8 @@ public:
|
||||||
/// Format the file system.
|
/// Format the file system.
|
||||||
virtual ResultCode Format(Uid uid) = 0;
|
virtual ResultCode Format(Uid uid) = 0;
|
||||||
|
|
||||||
/// Get a file descriptor for accessing a file.
|
/// Get a file descriptor for accessing a file. The FD will be automatically closed after use.
|
||||||
virtual Result<Fd> OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) = 0;
|
virtual Result<FileHandle> OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) = 0;
|
||||||
/// Close a file descriptor.
|
/// Close a file descriptor.
|
||||||
virtual ResultCode Close(Fd fd) = 0;
|
virtual ResultCode Close(Fd fd) = 0;
|
||||||
/// Read `size` bytes from the file descriptor. Returns the number of bytes read.
|
/// Read `size` bytes from the file descriptor. Returns the number of bytes read.
|
||||||
|
|
|
@ -70,13 +70,13 @@ IPCCommandResult FS::Open(const OpenRequest& request)
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto backend_fd = m_ios.GetFS()->OpenFile(request.uid, request.gid, request.path,
|
auto backend_fd = m_ios.GetFS()->OpenFile(request.uid, request.gid, request.path,
|
||||||
static_cast<Mode>(request.flags & 3));
|
static_cast<Mode>(request.flags & 3));
|
||||||
LogResult(StringFromFormat("OpenFile(%s)", request.path.c_str()), backend_fd);
|
LogResult(StringFromFormat("OpenFile(%s)", request.path.c_str()), backend_fd);
|
||||||
if (!backend_fd)
|
if (!backend_fd)
|
||||||
return GetFSReply(ConvertResult(backend_fd.Error()));
|
return GetFSReply(ConvertResult(backend_fd.Error()));
|
||||||
|
|
||||||
m_fd_map[request.fd] = {request.gid, request.uid, *backend_fd};
|
m_fd_map[request.fd] = {request.gid, request.uid, backend_fd->Release()};
|
||||||
std::strncpy(m_fd_map[request.fd].name.data(), request.path.c_str(), 64);
|
std::strncpy(m_fd_map[request.fd].name.data(), request.path.c_str(), 64);
|
||||||
return GetFSReply(IPC_SUCCESS);
|
return GetFSReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
ResultCode Format(Uid uid) override;
|
ResultCode Format(Uid uid) override;
|
||||||
|
|
||||||
Result<Fd> OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) override;
|
Result<FileHandle> OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) override;
|
||||||
ResultCode Close(Fd fd) override;
|
ResultCode Close(Fd fd) override;
|
||||||
Result<u32> ReadBytesFromFile(Fd fd, u8* ptr, u32 size) override;
|
Result<u32> ReadBytesFromFile(Fd fd, u8* ptr, u32 size) override;
|
||||||
Result<u32> WriteBytesToFile(Fd fd, const u8* ptr, u32 size) override;
|
Result<u32> WriteBytesToFile(Fd fd, const u8* ptr, u32 size) override;
|
||||||
|
|
|
@ -57,7 +57,7 @@ std::shared_ptr<File::IOFile> HostFileSystem::OpenHostFile(const std::string& ho
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Fd> HostFileSystem::OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode)
|
Result<FileHandle> HostFileSystem::OpenFile(Uid, Gid, const std::string& path, Mode mode)
|
||||||
{
|
{
|
||||||
Handle* handle = AssignFreeHandle();
|
Handle* handle = AssignFreeHandle();
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
@ -74,7 +74,7 @@ Result<Fd> HostFileSystem::OpenFile(Uid uid, Gid gid, const std::string& path, M
|
||||||
handle->wii_path = path;
|
handle->wii_path = path;
|
||||||
handle->mode = mode;
|
handle->mode = mode;
|
||||||
handle->file_offset = 0;
|
handle->file_offset = 0;
|
||||||
return ConvertHandleToFd(handle);
|
return FileHandle{this, ConvertHandleToFd(handle)};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode HostFileSystem::Close(Fd fd)
|
ResultCode HostFileSystem::Close(Fd fd)
|
||||||
|
|
Loading…
Reference in New Issue