Merge pull request #7059 from leoetlino/fs-wiisave
WiiSave: Use new filesystem interface
This commit is contained in:
commit
8fce18e4ff
|
@ -478,8 +478,8 @@ void UpdateStateFlags(std::function<void(StateFlags*)> update_function)
|
|||
const std::string file_path = Common::GetTitleDataPath(Titles::SYSTEM_MENU) + "/" WII_STATE;
|
||||
const auto fs = IOS::HLE::GetIOS()->GetFS();
|
||||
constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
const auto file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, file_path, rw_mode,
|
||||
rw_mode, rw_mode);
|
||||
const auto file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, file_path,
|
||||
{rw_mode, rw_mode, rw_mode});
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ bool CBoot::SetupWiiMemory()
|
|||
|
||||
constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
const auto settings_file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID,
|
||||
settings_file_path, rw_mode, rw_mode, rw_mode);
|
||||
settings_file_path, {rw_mode, rw_mode, rw_mode});
|
||||
if (!settings_file || !settings_file->Write(gen.GetBytes().data(), gen.GetBytes().size()))
|
||||
{
|
||||
PanicAlertT("SetupWiiMemory: Can't create setting.txt file");
|
||||
|
@ -343,7 +343,7 @@ static void WriteEmptyPlayRecord()
|
|||
const auto fs = IOS::HLE::GetIOS()->GetFS();
|
||||
constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
const auto playrec_file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, file_path,
|
||||
rw_mode, rw_mode, rw_mode);
|
||||
{rw_mode, rw_mode, rw_mode});
|
||||
if (!playrec_file)
|
||||
return;
|
||||
std::vector<u8> empty_record(0x80);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Common/Swap.h"
|
||||
#include "Core/CommonTitles.h"
|
||||
#include "Core/IOS/ES/ES.h"
|
||||
#include "Core/IOS/FS/FileSystem.h"
|
||||
#include "Core/IOS/IOS.h"
|
||||
#include "Core/IOS/IOSC.h"
|
||||
#include "Core/IOS/Uids.h"
|
||||
|
@ -141,31 +142,39 @@ void StorageDeleter::operator()(Storage* p) const
|
|||
delete p;
|
||||
}
|
||||
|
||||
namespace FS = IOS::HLE::FS;
|
||||
|
||||
class NandStorage final : public Storage
|
||||
{
|
||||
public:
|
||||
explicit NandStorage(u64 tid) : m_tid{tid}
|
||||
explicit NandStorage(FS::FileSystem* fs, u64 tid) : m_fs{fs}, m_tid{tid}
|
||||
{
|
||||
m_wii_title_path = Common::GetTitleDataPath(tid, Common::FromWhichRoot::FROM_CONFIGURED_ROOT);
|
||||
File::CreateFullPath(m_wii_title_path);
|
||||
ScanForFiles();
|
||||
m_data_dir = Common::GetTitleDataPath(tid);
|
||||
InitTitleUidAndGid();
|
||||
ScanForFiles(m_data_dir);
|
||||
}
|
||||
|
||||
bool SaveExists() override { return File::Exists(m_wii_title_path + "/banner.bin"); }
|
||||
bool SaveExists() override
|
||||
{
|
||||
return m_uid && m_gid && m_fs->GetMetadata(*m_uid, *m_gid, m_data_dir + "/banner.bin");
|
||||
}
|
||||
|
||||
std::optional<Header> ReadHeader() override
|
||||
{
|
||||
if (!m_uid || !m_gid)
|
||||
return {};
|
||||
|
||||
const auto banner = m_fs->OpenFile(*m_uid, *m_gid, m_data_dir + "/banner.bin", FS::Mode::Read);
|
||||
if (!banner)
|
||||
return {};
|
||||
Header header{};
|
||||
std::string banner_file_path = m_wii_title_path + "/banner.bin";
|
||||
u32 banner_size = static_cast<u32>(File::GetSize(banner_file_path));
|
||||
header.banner_size = banner_size;
|
||||
header.banner_size = banner->GetStatus()->size;
|
||||
header.tid = m_tid;
|
||||
header.md5 = s_md5_blanker;
|
||||
header.permissions = 0x3C;
|
||||
|
||||
File::IOFile banner_file(banner_file_path, "rb");
|
||||
if (!banner_file.ReadBytes(header.banner, banner_size))
|
||||
const u8 mode = GetBinMode(m_data_dir + "/banner.bin");
|
||||
if (!mode || !banner->Read(header.banner, header.banner_size))
|
||||
return {};
|
||||
header.permissions = mode;
|
||||
// remove nocopy flag
|
||||
header.banner[7] &= ~1;
|
||||
|
||||
|
@ -188,58 +197,44 @@ public:
|
|||
return bk_hdr;
|
||||
}
|
||||
|
||||
std::optional<std::vector<SaveFile>> ReadFiles() override
|
||||
{
|
||||
std::vector<SaveFile> ret(m_files_list.size());
|
||||
std::transform(m_files_list.begin(), m_files_list.end(), ret.begin(), [this](const auto& path) {
|
||||
const File::FileInfo file_info{path};
|
||||
SaveFile save_file;
|
||||
save_file.mode = 0x3c;
|
||||
save_file.attributes = 0;
|
||||
save_file.type = file_info.IsDirectory() ? SaveFile::Type::Directory : SaveFile::Type::File;
|
||||
save_file.path = Common::UnescapeFileName(path.substr(m_wii_title_path.length() + 1));
|
||||
save_file.data = [path]() -> std::optional<std::vector<u8>> {
|
||||
File::IOFile file{path, "rb"};
|
||||
std::vector<u8> data(file.GetSize());
|
||||
if (!file || !file.ReadBytes(data.data(), data.size()))
|
||||
return std::nullopt;
|
||||
return data;
|
||||
};
|
||||
return save_file;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
std::optional<std::vector<SaveFile>> ReadFiles() override { return m_files_list; }
|
||||
|
||||
bool WriteHeader(const Header& header) override
|
||||
{
|
||||
File::IOFile banner_file(m_wii_title_path + "/banner.bin", "wb");
|
||||
return banner_file.WriteBytes(header.banner, header.banner_size);
|
||||
if (!m_uid || !m_gid)
|
||||
return false;
|
||||
|
||||
const std::string banner_file_path = m_data_dir + "/banner.bin";
|
||||
const FS::Modes modes = GetFsMode(header.permissions);
|
||||
const auto file = m_fs->CreateAndOpenFile(*m_uid, *m_gid, banner_file_path, modes);
|
||||
return file && file->Write(header.banner, header.banner_size);
|
||||
}
|
||||
|
||||
bool WriteBkHeader(const BkHeader& bk_header) override { return true; }
|
||||
|
||||
bool WriteFiles(const std::vector<SaveFile>& files) override
|
||||
{
|
||||
if (!m_uid || !m_gid)
|
||||
return false;
|
||||
|
||||
for (const SaveFile& file : files)
|
||||
{
|
||||
// Allows files in subfolders to be escaped properly (ex: "nocopy/data00")
|
||||
// Special characters in path components will be escaped such as /../
|
||||
std::string file_path = Common::EscapePath(file.path);
|
||||
std::string file_path_full = m_wii_title_path + '/' + file_path;
|
||||
File::CreateFullPath(file_path_full);
|
||||
|
||||
const FS::Modes modes = GetFsMode(file.mode);
|
||||
if (file.type == SaveFile::Type::File)
|
||||
{
|
||||
File::IOFile raw_save_file(file_path_full, "wb");
|
||||
const auto raw_file = m_fs->CreateAndOpenFile(*m_uid, *m_gid, file.path, modes);
|
||||
const std::optional<std::vector<u8>>& data = *file.data;
|
||||
if (!data)
|
||||
if (!data || !raw_file || !raw_file->Write(data->data(), data->size()))
|
||||
return false;
|
||||
raw_save_file.WriteBytes(data->data(), data->size());
|
||||
}
|
||||
else if (file.type == SaveFile::Type::Directory)
|
||||
{
|
||||
File::CreateDir(file_path_full);
|
||||
if (!File::IsDirectory(file_path_full))
|
||||
const FS::Result<FS::Metadata> meta = m_fs->GetMetadata(*m_uid, *m_gid, file.path);
|
||||
if (!meta || meta->is_file)
|
||||
return false;
|
||||
|
||||
const FS::ResultCode result = m_fs->CreateDirectory(*m_uid, *m_gid, file.path, 0, modes);
|
||||
if (result != FS::ResultCode::Success)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -247,50 +242,81 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void ScanForFiles()
|
||||
void ScanForFiles(const std::string& dir)
|
||||
{
|
||||
std::vector<std::string> directories;
|
||||
directories.push_back(m_wii_title_path);
|
||||
u32 size = 0;
|
||||
if (!m_uid || !m_gid)
|
||||
return;
|
||||
|
||||
for (u32 i = 0; i < directories.size(); ++i)
|
||||
const auto entries = m_fs->ReadDirectory(*m_uid, *m_gid, dir);
|
||||
if (!entries)
|
||||
return;
|
||||
|
||||
for (const std::string& elem : *entries)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
// add dir to fst
|
||||
m_files_list.push_back(directories[i]);
|
||||
}
|
||||
if (elem == "banner.bin")
|
||||
continue;
|
||||
|
||||
File::FSTEntry fst_tmp = File::ScanDirectoryTree(directories[i], false);
|
||||
for (const File::FSTEntry& elem : fst_tmp.children)
|
||||
{
|
||||
if (elem.virtualName != "banner.bin")
|
||||
{
|
||||
size += sizeof(FileHDR);
|
||||
if (elem.isDirectory)
|
||||
{
|
||||
if (elem.virtualName == "nocopy" || elem.virtualName == "nomove")
|
||||
{
|
||||
NOTICE_LOG(CONSOLE,
|
||||
"This save will likely require homebrew tools to copy to a real Wii.");
|
||||
}
|
||||
const std::string path = dir + '/' + elem;
|
||||
const FS::Result<FS::Metadata> metadata = m_fs->GetMetadata(*m_uid, *m_gid, path);
|
||||
if (!metadata)
|
||||
return;
|
||||
|
||||
directories.push_back(elem.physicalName);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_files_list.push_back(elem.physicalName);
|
||||
size += static_cast<u32>(Common::AlignUp(elem.size, BLOCK_SZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
SaveFile save_file;
|
||||
save_file.mode = GetBinMode(metadata->modes);
|
||||
save_file.attributes = 0;
|
||||
save_file.type = metadata->is_file ? SaveFile::Type::File : SaveFile::Type::Directory;
|
||||
save_file.path = path;
|
||||
save_file.data = [this, path]() -> std::optional<std::vector<u8>> {
|
||||
const auto file = m_fs->OpenFile(*m_uid, *m_gid, path, FS::Mode::Read);
|
||||
if (!file)
|
||||
return {};
|
||||
std::vector<u8> data(file->GetStatus()->size);
|
||||
if (!file->Read(data.data(), data.size()))
|
||||
return std::nullopt;
|
||||
return data;
|
||||
};
|
||||
m_files_list.emplace_back(std::move(save_file));
|
||||
m_files_size += sizeof(FileHDR);
|
||||
|
||||
if (metadata->is_file)
|
||||
m_files_size += static_cast<u32>(Common::AlignUp(metadata->size, BLOCK_SZ));
|
||||
else
|
||||
ScanForFiles(path);
|
||||
}
|
||||
m_files_size = size;
|
||||
}
|
||||
|
||||
void InitTitleUidAndGid()
|
||||
{
|
||||
const auto metadata = m_fs->GetMetadata(IOS::PID_KERNEL, IOS::PID_KERNEL, m_data_dir);
|
||||
if (!metadata)
|
||||
return;
|
||||
m_uid = metadata->uid;
|
||||
m_gid = metadata->gid;
|
||||
}
|
||||
|
||||
static constexpr FS::Modes GetFsMode(u8 bin_mode)
|
||||
{
|
||||
return {FS::Mode(bin_mode >> 4 & 3), FS::Mode(bin_mode >> 2 & 3), FS::Mode(bin_mode >> 0 & 3)};
|
||||
}
|
||||
|
||||
static constexpr u8 GetBinMode(const FS::Modes& modes)
|
||||
{
|
||||
return u8(modes.owner) << 4 | u8(modes.group) << 2 | u8(modes.other) << 0;
|
||||
}
|
||||
|
||||
u8 GetBinMode(const std::string& path) const
|
||||
{
|
||||
if (const FS::Result<FS::Metadata> meta = m_fs->GetMetadata(*m_uid, *m_gid, path))
|
||||
return GetBinMode(meta->modes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FS::FileSystem* m_fs = nullptr;
|
||||
std::string m_data_dir;
|
||||
u64 m_tid = 0;
|
||||
std::string m_wii_title_path;
|
||||
std::vector<std::string> m_files_list;
|
||||
std::optional<u32> m_uid;
|
||||
std::optional<u16> m_gid;
|
||||
std::vector<SaveFile> m_files_list;
|
||||
u32 m_files_size = 0;
|
||||
};
|
||||
|
||||
|
@ -487,10 +513,9 @@ private:
|
|||
File::IOFile m_file;
|
||||
};
|
||||
|
||||
StoragePointer MakeNandStorage(IOS::HLE::FS::FileSystem* fs, u64 tid)
|
||||
StoragePointer MakeNandStorage(FS::FileSystem* fs, u64 tid)
|
||||
{
|
||||
// fs parameter is not used yet but will be after WiiSave is migrated to the new FS interface.
|
||||
return StoragePointer{new NandStorage{tid}};
|
||||
return StoragePointer{new NandStorage{fs, tid}};
|
||||
}
|
||||
|
||||
StoragePointer MakeDataBinStorage(IOS::HLE::IOSC* iosc, const std::string& path, const char* mode)
|
||||
|
|
|
@ -39,24 +39,22 @@ struct DirectoryToCreate
|
|||
{
|
||||
const char* path;
|
||||
FS::FileAttribute attribute;
|
||||
FS::Mode owner_mode;
|
||||
FS::Mode group_mode;
|
||||
FS::Mode other_mode;
|
||||
FS::Modes modes;
|
||||
FS::Uid uid = PID_KERNEL;
|
||||
FS::Gid gid = PID_KERNEL;
|
||||
};
|
||||
|
||||
constexpr FS::Modes public_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite};
|
||||
constexpr std::array<DirectoryToCreate, 9> s_directories_to_create = {{
|
||||
{"/sys", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None},
|
||||
{"/ticket", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None},
|
||||
{"/title", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read},
|
||||
{"/shared1", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None},
|
||||
{"/shared2", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite},
|
||||
{"/tmp", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite},
|
||||
{"/import", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None},
|
||||
{"/meta", 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite, SYSMENU_UID,
|
||||
SYSMENU_GID},
|
||||
{"/wfs", 0, FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None, PID_UNKNOWN, PID_UNKNOWN},
|
||||
{"/sys", 0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None}},
|
||||
{"/ticket", 0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None}},
|
||||
{"/title", 0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read}},
|
||||
{"/shared1", 0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None}},
|
||||
{"/shared2", 0, public_modes},
|
||||
{"/tmp", 0, public_modes},
|
||||
{"/import", 0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None}},
|
||||
{"/meta", 0, public_modes, SYSMENU_UID, SYSMENU_GID},
|
||||
{"/wfs", 0, {FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None}, PID_UNKNOWN, PID_UNKNOWN},
|
||||
}};
|
||||
|
||||
ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
|
||||
|
@ -66,14 +64,13 @@ ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
|
|||
// Note: ES sets its own UID and GID to 0/0 at boot, so all filesystem accesses in ES are done
|
||||
// as UID 0 even though its PID is 1.
|
||||
const auto result = m_ios.GetFS()->CreateDirectory(PID_KERNEL, PID_KERNEL, directory.path,
|
||||
directory.attribute, directory.owner_mode,
|
||||
directory.group_mode, directory.other_mode);
|
||||
directory.attribute, directory.modes);
|
||||
if (result != FS::ResultCode::Success && result != FS::ResultCode::AlreadyExists)
|
||||
ERROR_LOG(IOS_ES, "Failed to create %s: error %d", directory.path, FS::ConvertResult(result));
|
||||
|
||||
// Now update the UID/GID and other attributes.
|
||||
m_ios.GetFS()->SetMetadata(0, directory.path, directory.uid, directory.gid, directory.attribute,
|
||||
directory.owner_mode, directory.group_mode, directory.other_mode);
|
||||
directory.modes);
|
||||
}
|
||||
|
||||
FinishAllStaleImports();
|
||||
|
@ -623,9 +620,9 @@ static s32 WriteTmdForDiVerify(FS::FileSystem* fs, const IOS::ES::TMDReader& tmd
|
|||
{
|
||||
const std::string temp_path = "/tmp/title.tmd";
|
||||
fs->Delete(PID_KERNEL, PID_KERNEL, temp_path);
|
||||
constexpr FS::Modes internal_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
||||
{
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::None);
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, internal_modes);
|
||||
if (!file)
|
||||
return FS::ConvertResult(file.Error());
|
||||
if (!file->Write(tmd.GetBytes().data(), tmd.GetBytes().size()))
|
||||
|
@ -634,13 +631,12 @@ static s32 WriteTmdForDiVerify(FS::FileSystem* fs, const IOS::ES::TMDReader& tmd
|
|||
|
||||
const std::string tmd_dir = Common::GetTitleContentPath(tmd.GetTitleId());
|
||||
const std::string tmd_path = Common::GetTMDFileName(tmd.GetTitleId());
|
||||
const auto result = fs->CreateFullPath(PID_KERNEL, PID_KERNEL, tmd_path, 0, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::Read);
|
||||
constexpr FS::Modes parent_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read};
|
||||
const auto result = fs->CreateFullPath(PID_KERNEL, PID_KERNEL, tmd_path, 0, parent_modes);
|
||||
if (result != FS::ResultCode::Success)
|
||||
return FS::ConvertResult(result);
|
||||
|
||||
fs->SetMetadata(PID_KERNEL, tmd_dir, PID_KERNEL, PID_KERNEL, 0, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::None);
|
||||
fs->SetMetadata(PID_KERNEL, tmd_dir, PID_KERNEL, PID_KERNEL, 0, internal_modes);
|
||||
return FS::ConvertResult(fs->Rename(PID_KERNEL, PID_KERNEL, temp_path, tmd_path));
|
||||
}
|
||||
|
||||
|
@ -678,10 +674,10 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
|
|||
|
||||
const std::string data_dir = Common::GetTitleDataPath(tmd.GetTitleId());
|
||||
// Might already exist, so we only need to check whether the second operation succeeded.
|
||||
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0, FS::Mode::ReadWrite, FS::Mode::None,
|
||||
FS::Mode::None);
|
||||
return FS::ConvertResult(fs->SetMetadata(0, data_dir, m_ios.GetUidForPPC(), m_ios.GetGidForPPC(),
|
||||
0, FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None));
|
||||
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
||||
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0, data_dir_modes);
|
||||
return FS::ConvertResult(
|
||||
fs->SetMetadata(0, data_dir, m_ios.GetUidForPPC(), m_ios.GetGidForPPC(), 0, data_dir_modes));
|
||||
}
|
||||
|
||||
ReturnCode ES::CheckStreamKeyPermissions(const u32 uid, const u8* ticket_view,
|
||||
|
@ -877,8 +873,8 @@ ReturnCode ES::WriteNewCertToStore(const IOS::ES::CertReader& cert)
|
|||
|
||||
// Otherwise, write the new cert at the end of the store.
|
||||
const auto store_file =
|
||||
m_ios.GetFS()->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, CERT_STORE_PATH, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::Read);
|
||||
m_ios.GetFS()->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, CERT_STORE_PATH,
|
||||
{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read});
|
||||
if (!store_file || !store_file->Seek(0, FS::SeekMode::End) ||
|
||||
!store_file->Write(cert.GetBytes().data(), cert.GetBytes().size()))
|
||||
{
|
||||
|
|
|
@ -591,9 +591,9 @@ bool SharedContentMap::WriteEntries() const
|
|||
const std::string temp_path = "/tmp/content.map";
|
||||
// Atomically write the new content map.
|
||||
{
|
||||
const auto file =
|
||||
m_fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, HLE::FS::Mode::ReadWrite,
|
||||
HLE::FS::Mode::ReadWrite, HLE::FS::Mode::None);
|
||||
constexpr HLE::FS::Modes modes{HLE::FS::Mode::ReadWrite, HLE::FS::Mode::ReadWrite,
|
||||
HLE::FS::Mode::None};
|
||||
const auto file = m_fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, modes);
|
||||
if (!file || !file->Write(m_entries.data(), m_entries.size()))
|
||||
return false;
|
||||
}
|
||||
|
@ -665,9 +665,9 @@ u32 UIDSys::GetOrInsertUIDForTitle(const u64 title_id)
|
|||
const u64 swapped_title_id = Common::swap64(title_id);
|
||||
const u32 swapped_uid = Common::swap32(uid);
|
||||
|
||||
const auto file =
|
||||
m_fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, HLE::FS::Mode::ReadWrite,
|
||||
HLE::FS::Mode::ReadWrite, HLE::FS::Mode::None);
|
||||
constexpr HLE::FS::Modes modes{HLE::FS::Mode::ReadWrite, HLE::FS::Mode::ReadWrite,
|
||||
HLE::FS::Mode::None};
|
||||
const auto file = m_fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, UID_MAP_PATH, modes);
|
||||
if (!file || !file->Seek(0, HLE::FS::SeekMode::End) || !file->Write(&swapped_title_id, 1) ||
|
||||
!file->Write(&swapped_uid, 1))
|
||||
{
|
||||
|
|
|
@ -222,15 +222,19 @@ static bool DeleteDirectoriesIfEmpty(FS::FileSystem* fs, const std::string& path
|
|||
return true;
|
||||
}
|
||||
|
||||
constexpr FS::Modes title_dir_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read};
|
||||
constexpr FS::Modes content_dir_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
||||
constexpr FS::Modes data_dir_modes{FS::Mode::ReadWrite, FS::Mode::None, FS::Mode::None};
|
||||
|
||||
bool ES::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
||||
{
|
||||
const auto fs = m_ios.GetFS();
|
||||
|
||||
const std::string content_dir = Common::GetTitleContentPath(title_id);
|
||||
const auto result1 = fs->CreateFullPath(PID_KERNEL, PID_KERNEL, content_dir + '/', 0,
|
||||
FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::Read);
|
||||
const auto result2 = fs->SetMetadata(PID_KERNEL, content_dir, PID_KERNEL, PID_KERNEL, 0,
|
||||
FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None);
|
||||
const auto result1 =
|
||||
fs->CreateFullPath(PID_KERNEL, PID_KERNEL, content_dir + '/', 0, title_dir_modes);
|
||||
const auto result2 =
|
||||
fs->SetMetadata(PID_KERNEL, content_dir, PID_KERNEL, PID_KERNEL, 0, content_dir_modes);
|
||||
if (result1 != FS::ResultCode::Success || result2 != FS::ResultCode::Success)
|
||||
{
|
||||
ERROR_LOG(IOS_ES, "Failed to create or set metadata on content dir for %016" PRIx64, title_id);
|
||||
|
@ -239,10 +243,9 @@ bool ES::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
|||
|
||||
const std::string data_dir = Common::GetTitleDataPath(title_id);
|
||||
const auto data_dir_contents = fs->ReadDirectory(PID_KERNEL, PID_KERNEL, data_dir);
|
||||
if (!data_dir_contents &&
|
||||
(data_dir_contents.Error() != FS::ResultCode::NotFound ||
|
||||
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0, FS::Mode::ReadWrite, FS::Mode::None,
|
||||
FS::Mode::None) != FS::ResultCode::Success))
|
||||
if (!data_dir_contents && (data_dir_contents.Error() != FS::ResultCode::NotFound ||
|
||||
fs->CreateDirectory(PID_KERNEL, PID_KERNEL, data_dir, 0,
|
||||
data_dir_modes) != FS::ResultCode::Success))
|
||||
{
|
||||
ERROR_LOG(IOS_ES, "Failed to create data dir for %016" PRIx64, title_id);
|
||||
return false;
|
||||
|
@ -250,8 +253,7 @@ bool ES::CreateTitleDirectories(u64 title_id, u16 group_id) const
|
|||
|
||||
IOS::ES::UIDSys uid_sys{fs};
|
||||
const u32 uid = uid_sys.GetOrInsertUIDForTitle(title_id);
|
||||
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, FS::Mode::ReadWrite, FS::Mode::None,
|
||||
FS::Mode::None) != FS::ResultCode::Success)
|
||||
if (fs->SetMetadata(0, data_dir, uid, group_id, 0, data_dir_modes) != FS::ResultCode::Success)
|
||||
{
|
||||
ERROR_LOG(IOS_ES, "Failed to set metadata on data dir for %016" PRIx64, title_id);
|
||||
return false;
|
||||
|
@ -267,8 +269,8 @@ bool ES::InitImport(const IOS::ES::TMDReader& tmd)
|
|||
|
||||
const auto fs = m_ios.GetFS();
|
||||
const std::string import_content_dir = Common::GetImportTitlePath(tmd.GetTitleId()) + "/content";
|
||||
const auto result = fs->CreateFullPath(PID_KERNEL, PID_KERNEL, import_content_dir + '/', 0,
|
||||
FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None);
|
||||
const auto result =
|
||||
fs->CreateFullPath(PID_KERNEL, PID_KERNEL, import_content_dir + '/', 0, content_dir_modes);
|
||||
if (result != FS::ResultCode::Success)
|
||||
{
|
||||
ERROR_LOG(IOS_ES, "InitImport: Failed to create content dir for %016" PRIx64, tmd.GetTitleId());
|
||||
|
@ -330,8 +332,7 @@ bool ES::WriteImportTMD(const IOS::ES::TMDReader& tmd)
|
|||
const auto fs = m_ios.GetFS();
|
||||
const std::string tmd_path = "/tmp/title.tmd";
|
||||
{
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, tmd_path, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::None);
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, tmd_path, content_dir_modes);
|
||||
if (!file || !file->Write(tmd.GetBytes().data(), tmd.GetBytes().size()))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -33,11 +33,9 @@ static ReturnCode WriteTicket(FS::FileSystem* fs, const IOS::ES::TicketReader& t
|
|||
const u64 title_id = ticket.GetTitleId();
|
||||
|
||||
const std::string path = Common::GetTicketFileName(title_id);
|
||||
fs->CreateFullPath(PID_KERNEL, PID_KERNEL, path, 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite,
|
||||
FS::Mode::None);
|
||||
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, path, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::None);
|
||||
constexpr FS::Modes ticket_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
||||
fs->CreateFullPath(PID_KERNEL, PID_KERNEL, path, 0, ticket_modes);
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, path, ticket_modes);
|
||||
if (!file)
|
||||
return FS::ConvertResult(file.Error());
|
||||
|
||||
|
@ -400,8 +398,8 @@ ReturnCode ES::ImportContentEnd(Context& context, u32 content_fd)
|
|||
"/tmp/" + content_path.substr(content_path.find_last_of('/') + 1, std::string::npos);
|
||||
|
||||
{
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::None);
|
||||
constexpr FS::Modes content_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::None};
|
||||
const auto file = fs->CreateAndOpenFile(PID_KERNEL, PID_KERNEL, temp_path, content_modes);
|
||||
if (!file || !file->Write(decrypted_data.data(), content_info.size))
|
||||
{
|
||||
ERROR_LOG(IOS_ES, "ImportContentEnd: Failed to write to %s", temp_path.c_str());
|
||||
|
|
|
@ -69,17 +69,17 @@ Result<FileStatus> FileHandle::GetStatus() const
|
|||
void FileSystem::Init()
|
||||
{
|
||||
if (Delete(0, 0, "/tmp") == ResultCode::Success)
|
||||
CreateDirectory(0, 0, "/tmp", 0, Mode::ReadWrite, Mode::ReadWrite, Mode::ReadWrite);
|
||||
CreateDirectory(0, 0, "/tmp", 0, {Mode::ReadWrite, Mode::ReadWrite, Mode::ReadWrite});
|
||||
}
|
||||
|
||||
Result<FileHandle> FileSystem::CreateAndOpenFile(Uid uid, Gid gid, const std::string& path,
|
||||
Mode owner_mode, Mode group_mode, Mode other_mode)
|
||||
Modes modes)
|
||||
{
|
||||
Result<FileHandle> file = OpenFile(uid, gid, path, Mode::ReadWrite);
|
||||
if (file.Succeeded())
|
||||
return file;
|
||||
|
||||
const ResultCode result = CreateFile(uid, gid, path, 0, owner_mode, group_mode, other_mode);
|
||||
const ResultCode result = CreateFile(uid, gid, path, 0, modes);
|
||||
if (result != ResultCode::Success)
|
||||
return result;
|
||||
|
||||
|
@ -87,7 +87,7 @@ Result<FileHandle> FileSystem::CreateAndOpenFile(Uid uid, Gid gid, const std::st
|
|||
}
|
||||
|
||||
ResultCode FileSystem::CreateFullPath(Uid uid, Gid gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner, Mode group, Mode other)
|
||||
FileAttribute attribute, Modes modes)
|
||||
{
|
||||
std::string::size_type position = 1;
|
||||
while (true)
|
||||
|
@ -103,7 +103,7 @@ ResultCode FileSystem::CreateFullPath(Uid uid, Gid gid, const std::string& path,
|
|||
if (metadata && metadata->is_file)
|
||||
return ResultCode::Invalid;
|
||||
|
||||
const ResultCode result = CreateDirectory(uid, gid, subpath, attribute, owner, group, other);
|
||||
const ResultCode result = CreateDirectory(uid, gid, subpath, attribute, modes);
|
||||
if (result != ResultCode::Success && result != ResultCode::AlreadyExists)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -67,12 +67,17 @@ enum class SeekMode : u32
|
|||
|
||||
using FileAttribute = u8;
|
||||
|
||||
struct Modes
|
||||
{
|
||||
Mode owner, group, other;
|
||||
};
|
||||
|
||||
struct Metadata
|
||||
{
|
||||
Uid uid;
|
||||
Gid gid;
|
||||
FileAttribute attribute;
|
||||
Mode owner_mode, group_mode, other_mode;
|
||||
Modes modes;
|
||||
bool is_file;
|
||||
u32 size;
|
||||
u16 fst_index;
|
||||
|
@ -142,8 +147,7 @@ public:
|
|||
/// Get a file descriptor for accessing a file. The FD will be automatically closed after use.
|
||||
virtual Result<FileHandle> OpenFile(Uid uid, Gid gid, const std::string& path, Mode mode) = 0;
|
||||
/// Create a file if it doesn't exist and open it in read/write mode.
|
||||
Result<FileHandle> CreateAndOpenFile(Uid uid, Gid gid, const std::string& path, Mode owner_mode,
|
||||
Mode group_mode, Mode other_mode);
|
||||
Result<FileHandle> CreateAndOpenFile(Uid uid, Gid gid, const std::string& path, Modes modes);
|
||||
/// Close a file descriptor.
|
||||
virtual ResultCode Close(Fd fd) = 0;
|
||||
/// Read `size` bytes from the file descriptor. Returns the number of bytes read.
|
||||
|
@ -157,17 +161,15 @@ public:
|
|||
|
||||
/// Create a file with the specified path and metadata.
|
||||
virtual ResultCode CreateFile(Uid caller_uid, Gid caller_gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) = 0;
|
||||
FileAttribute attribute, Modes modes) = 0;
|
||||
/// Create a directory with the specified path and metadata.
|
||||
virtual ResultCode CreateDirectory(Uid caller_uid, Gid caller_gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) = 0;
|
||||
FileAttribute attribute, Modes modes) = 0;
|
||||
|
||||
/// Create any parent directories for a path with the specified metadata.
|
||||
/// Example: "/a/b" to create directory /a; "/a/b/" to create directories /a and /a/b
|
||||
ResultCode CreateFullPath(Uid caller_uid, Gid caller_gid, const std::string& path,
|
||||
FileAttribute attribute, Mode ownerm, Mode group, Mode other);
|
||||
FileAttribute attribute, Modes modes);
|
||||
|
||||
/// Delete a file or directory with the specified path.
|
||||
virtual ResultCode Delete(Uid caller_uid, Gid caller_gid, const std::string& path) = 0;
|
||||
|
@ -183,8 +185,7 @@ public:
|
|||
virtual Result<Metadata> GetMetadata(Uid caller_uid, Gid caller_gid, const std::string& path) = 0;
|
||||
/// Set metadata for a file.
|
||||
virtual ResultCode SetMetadata(Uid caller_uid, const std::string& path, Uid uid, Gid gid,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) = 0;
|
||||
FileAttribute attribute, Modes modes) = 0;
|
||||
|
||||
/// Get usage information about the NAND (block size, cluster and inode counts).
|
||||
virtual Result<NandStats> GetNandStats() = 0;
|
||||
|
|
|
@ -282,9 +282,7 @@ struct ISFSParams
|
|||
Common::BigEndianValue<Uid> uid;
|
||||
Common::BigEndianValue<Gid> gid;
|
||||
char path[64];
|
||||
Mode owner_mode;
|
||||
Mode group_mode;
|
||||
Mode other_mode;
|
||||
Modes modes;
|
||||
FileAttribute attribute;
|
||||
};
|
||||
|
||||
|
@ -406,9 +404,8 @@ IPCCommandResult FS::CreateDirectory(const Handle& handle, const IOCtlRequest& r
|
|||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
const ResultCode result =
|
||||
m_ios.GetFS()->CreateDirectory(handle.uid, handle.gid, params->path, params->attribute,
|
||||
params->owner_mode, params->group_mode, params->other_mode);
|
||||
const ResultCode result = m_ios.GetFS()->CreateDirectory(handle.uid, handle.gid, params->path,
|
||||
params->attribute, params->modes);
|
||||
LogResult(StringFromFormat("CreateDirectory(%s)", params->path), result);
|
||||
return GetReplyForSuperblockOperation(result);
|
||||
}
|
||||
|
@ -474,8 +471,7 @@ IPCCommandResult FS::SetAttribute(const Handle& handle, const IOCtlRequest& requ
|
|||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
const ResultCode result = m_ios.GetFS()->SetMetadata(
|
||||
handle.uid, params->path, params->uid, params->gid, params->attribute, params->owner_mode,
|
||||
params->group_mode, params->other_mode);
|
||||
handle.uid, params->path, params->uid, params->gid, params->attribute, params->modes);
|
||||
LogResult(StringFromFormat("SetMetadata(%s)", params->path), result);
|
||||
return GetReplyForSuperblockOperation(result);
|
||||
}
|
||||
|
@ -499,9 +495,7 @@ IPCCommandResult FS::GetAttribute(const Handle& handle, const IOCtlRequest& requ
|
|||
out.uid = metadata->uid;
|
||||
out.gid = metadata->gid;
|
||||
out.attribute = metadata->attribute;
|
||||
out.owner_mode = metadata->owner_mode;
|
||||
out.group_mode = metadata->group_mode;
|
||||
out.other_mode = metadata->other_mode;
|
||||
out.modes = metadata->modes;
|
||||
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
|
||||
return GetFSReply(IPC_SUCCESS, ticks);
|
||||
}
|
||||
|
@ -535,9 +529,8 @@ IPCCommandResult FS::CreateFile(const Handle& handle, const IOCtlRequest& reques
|
|||
if (!params)
|
||||
return GetFSReply(ConvertResult(params.Error()));
|
||||
|
||||
const ResultCode result =
|
||||
m_ios.GetFS()->CreateFile(handle.uid, handle.gid, params->path, params->attribute,
|
||||
params->owner_mode, params->group_mode, params->other_mode);
|
||||
const ResultCode result = m_ios.GetFS()->CreateFile(handle.uid, handle.gid, params->path,
|
||||
params->attribute, params->modes);
|
||||
LogResult(StringFromFormat("CreateFile(%s)", params->path), result);
|
||||
return GetReplyForSuperblockOperation(result);
|
||||
}
|
||||
|
|
|
@ -167,8 +167,7 @@ ResultCode HostFileSystem::Format(Uid uid)
|
|||
return ResultCode::Success;
|
||||
}
|
||||
|
||||
ResultCode HostFileSystem::CreateFile(Uid, Gid, const std::string& path, FileAttribute attribute,
|
||||
Mode owner_mode, Mode group_mode, Mode other_mode)
|
||||
ResultCode HostFileSystem::CreateFile(Uid, Gid, const std::string& path, FileAttribute, Modes)
|
||||
{
|
||||
std::string file_name(BuildFilename(path));
|
||||
// check if the file already exist
|
||||
|
@ -186,9 +185,7 @@ ResultCode HostFileSystem::CreateFile(Uid, Gid, const std::string& path, FileAtt
|
|||
return ResultCode::Success;
|
||||
}
|
||||
|
||||
ResultCode HostFileSystem::CreateDirectory(Uid, Gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner_mode,
|
||||
Mode group_mode, Mode other_mode)
|
||||
ResultCode HostFileSystem::CreateDirectory(Uid, Gid, const std::string& path, FileAttribute, Modes)
|
||||
{
|
||||
if (!IsValidWiiPath(path))
|
||||
return ResultCode::Invalid;
|
||||
|
@ -310,9 +307,7 @@ Result<Metadata> HostFileSystem::GetMetadata(Uid, Gid, const std::string& path)
|
|||
return ResultCode::Invalid;
|
||||
|
||||
std::string file_name = BuildFilename(path);
|
||||
metadata.owner_mode = Mode::ReadWrite;
|
||||
metadata.group_mode = Mode::ReadWrite;
|
||||
metadata.other_mode = Mode::ReadWrite;
|
||||
metadata.modes = {Mode::ReadWrite, Mode::ReadWrite, Mode::ReadWrite};
|
||||
metadata.attribute = 0x00; // no attributes
|
||||
|
||||
// Hack: if the path that is being accessed is within an installed title directory, get the
|
||||
|
@ -335,8 +330,7 @@ Result<Metadata> HostFileSystem::GetMetadata(Uid, Gid, const std::string& path)
|
|||
}
|
||||
|
||||
ResultCode HostFileSystem::SetMetadata(Uid caller_uid, const std::string& path, Uid uid, Gid gid,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode)
|
||||
FileAttribute, Modes)
|
||||
{
|
||||
if (!IsValidWiiPath(path))
|
||||
return ResultCode::Invalid;
|
||||
|
|
|
@ -38,12 +38,10 @@ public:
|
|||
Result<FileStatus> GetFileStatus(Fd fd) override;
|
||||
|
||||
ResultCode CreateFile(Uid caller_uid, Gid caller_gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) override;
|
||||
FileAttribute attribute, Modes modes) override;
|
||||
|
||||
ResultCode CreateDirectory(Uid caller_uid, Gid caller_gid, const std::string& path,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) override;
|
||||
FileAttribute attribute, Modes modes) override;
|
||||
|
||||
ResultCode Delete(Uid caller_uid, Gid caller_gid, const std::string& path) override;
|
||||
ResultCode Rename(Uid caller_uid, Gid caller_gid, const std::string& old_path,
|
||||
|
@ -54,8 +52,7 @@ public:
|
|||
|
||||
Result<Metadata> GetMetadata(Uid caller_uid, Gid caller_gid, const std::string& path) override;
|
||||
ResultCode SetMetadata(Uid caller_uid, const std::string& path, Uid uid, Gid gid,
|
||||
FileAttribute attribute, Mode owner_mode, Mode group_mode,
|
||||
Mode other_mode) override;
|
||||
FileAttribute attribute, Modes modes) override;
|
||||
|
||||
Result<NandStats> GetNandStats() override;
|
||||
Result<DirectoryStats> GetDirectoryStats(const std::string& path) override;
|
||||
|
|
|
@ -44,9 +44,9 @@ void NWC24Config::ReadConfig()
|
|||
|
||||
void NWC24Config::WriteConfig() const
|
||||
{
|
||||
constexpr FS::Mode rw_mode = FS::Mode::ReadWrite;
|
||||
m_fs->CreateFullPath(PID_KD, PID_KD, CONFIG_PATH, 0, rw_mode, rw_mode, rw_mode);
|
||||
const auto file = m_fs->CreateAndOpenFile(PID_KD, PID_KD, CONFIG_PATH, rw_mode, rw_mode, rw_mode);
|
||||
constexpr FS::Modes public_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite};
|
||||
m_fs->CreateFullPath(PID_KD, PID_KD, CONFIG_PATH, 0, public_modes);
|
||||
const auto file = m_fs->CreateAndOpenFile(PID_KD, PID_KD, CONFIG_PATH, public_modes);
|
||||
if (!file || !file->Write(&m_data, 1))
|
||||
ERROR_LOG(IOS_WC24, "Failed to open or write WC24 config file");
|
||||
}
|
||||
|
|
|
@ -36,10 +36,9 @@ void WiiNetConfig::ReadConfig(FS::FileSystem* fs)
|
|||
|
||||
void WiiNetConfig::WriteConfig(FS::FileSystem* fs) const
|
||||
{
|
||||
fs->CreateFullPath(PID_NCD, PID_NCD, CONFIG_PATH, 0, FS::Mode::ReadWrite, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite);
|
||||
const auto file = fs->CreateAndOpenFile(PID_NCD, PID_NCD, CONFIG_PATH, FS::Mode::ReadWrite,
|
||||
FS::Mode::ReadWrite, FS::Mode::ReadWrite);
|
||||
constexpr FS::Modes public_modes{FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite};
|
||||
fs->CreateFullPath(PID_NCD, PID_NCD, CONFIG_PATH, 0, public_modes);
|
||||
const auto file = fs->CreateAndOpenFile(PID_NCD, PID_NCD, CONFIG_PATH, public_modes);
|
||||
if (!file || !file->Write(&m_data, 1))
|
||||
ERROR_LOG(IOS_NET, "Failed to write config");
|
||||
}
|
||||
|
|
|
@ -199,13 +199,13 @@ bool SysConf::Save() const
|
|||
const std::string temp_file = "/tmp/SYSCONF";
|
||||
constexpr auto rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
{
|
||||
auto file = m_fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, temp_file, rw_mode,
|
||||
rw_mode, rw_mode);
|
||||
auto file = m_fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, temp_file,
|
||||
{rw_mode, rw_mode, rw_mode});
|
||||
if (!file || !file->Write(buffer.data(), buffer.size()))
|
||||
return false;
|
||||
}
|
||||
m_fs->CreateDirectory(IOS::SYSMENU_UID, IOS::SYSMENU_GID, "/shared2/sys", 0, rw_mode, rw_mode,
|
||||
rw_mode);
|
||||
m_fs->CreateDirectory(IOS::SYSMENU_UID, IOS::SYSMENU_GID, "/shared2/sys", 0,
|
||||
{rw_mode, rw_mode, rw_mode});
|
||||
const auto result =
|
||||
m_fs->Rename(IOS::SYSMENU_UID, IOS::SYSMENU_GID, temp_file, "/shared2/sys/SYSCONF");
|
||||
return result == IOS::HLE::FS::ResultCode::Success;
|
||||
|
|
|
@ -96,12 +96,11 @@ static bool CopySysmenuFilesToFS(IOS::HLE::FS::FileSystem* fs, const std::string
|
|||
const std::string host_path = host_source_path + '/' + entry.virtualName;
|
||||
const std::string nand_path = nand_target_path + '/' + entry.virtualName;
|
||||
constexpr IOS::HLE::FS::Mode rw_mode = IOS::HLE::FS::Mode::ReadWrite;
|
||||
constexpr IOS::HLE::FS::Modes public_modes{rw_mode, rw_mode, rw_mode};
|
||||
|
||||
if (entry.isDirectory)
|
||||
{
|
||||
fs->CreateDirectory(IOS::SYSMENU_UID, IOS::SYSMENU_GID, nand_path, 0, rw_mode, rw_mode,
|
||||
rw_mode);
|
||||
|
||||
fs->CreateDirectory(IOS::SYSMENU_UID, IOS::SYSMENU_GID, nand_path, 0, public_modes);
|
||||
if (!CopySysmenuFilesToFS(fs, host_path, nand_path))
|
||||
return false;
|
||||
}
|
||||
|
@ -116,8 +115,8 @@ static bool CopySysmenuFilesToFS(IOS::HLE::FS::FileSystem* fs, const std::string
|
|||
if (!host_file.ReadBytes(file_data.data(), file_data.size()))
|
||||
return false;
|
||||
|
||||
const auto nand_file = fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, nand_path,
|
||||
rw_mode, rw_mode, rw_mode);
|
||||
const auto nand_file =
|
||||
fs->CreateAndOpenFile(IOS::SYSMENU_UID, IOS::SYSMENU_GID, nand_path, public_modes);
|
||||
if (!nand_file || !nand_file->Write(file_data.data(), file_data.size()))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
using namespace IOS::HLE::FS;
|
||||
|
||||
constexpr Modes modes{Mode::ReadWrite, Mode::None, Mode::None};
|
||||
|
||||
class FileSystemTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
|
@ -50,8 +52,7 @@ TEST_F(FileSystemTest, CreateFile)
|
|||
{
|
||||
const std::string PATH = "/tmp/f";
|
||||
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, Mode::Read, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::Success);
|
||||
|
||||
const Result<Metadata> stats = m_fs->GetMetadata(Uid{0}, Gid{0}, PATH);
|
||||
ASSERT_TRUE(stats.Succeeded());
|
||||
|
@ -60,8 +61,7 @@ TEST_F(FileSystemTest, CreateFile)
|
|||
// TODO: After we start saving metadata correctly, check the UID, GID, permissions
|
||||
// as well (issue 10234).
|
||||
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, Mode::Read, Mode::None, Mode::None),
|
||||
ResultCode::AlreadyExists);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::AlreadyExists);
|
||||
|
||||
const Result<std::vector<std::string>> tmp_files = m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp");
|
||||
ASSERT_TRUE(tmp_files.Succeeded());
|
||||
|
@ -72,8 +72,7 @@ TEST_F(FileSystemTest, CreateDirectory)
|
|||
{
|
||||
const std::string PATH = "/tmp/d";
|
||||
|
||||
ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, Mode::Read, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::Success);
|
||||
|
||||
const Result<Metadata> stats = m_fs->GetMetadata(Uid{0}, Gid{0}, PATH);
|
||||
ASSERT_TRUE(stats.Succeeded());
|
||||
|
@ -112,15 +111,9 @@ TEST_F(FileSystemTest, RenameWithExistingTargetDirectory)
|
|||
// Test directory -> existing, non-empty directory.
|
||||
// IOS's FS sysmodule is not POSIX compliant and will remove the existing directory
|
||||
// if it exists, even when there are files in it.
|
||||
ASSERT_EQ(
|
||||
m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/d", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(
|
||||
m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/d2", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(
|
||||
m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/d2/file", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/d", 0, modes), ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/d2", 0, modes), ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/d2/file", 0, modes), ResultCode::Success);
|
||||
EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, "/tmp/d", "/tmp/d2"), ResultCode::Success);
|
||||
|
||||
EXPECT_EQ(m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp/d").Error(), ResultCode::NotFound);
|
||||
|
@ -132,8 +125,7 @@ TEST_F(FileSystemTest, RenameWithExistingTargetDirectory)
|
|||
TEST_F(FileSystemTest, RenameWithExistingTargetFile)
|
||||
{
|
||||
// Create the test source file and write some data (so that we can check its size later on).
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f1", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f1", 0, modes), ResultCode::Success);
|
||||
const std::vector<u8> TEST_DATA{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
|
||||
std::vector<u8> read_buffer(TEST_DATA.size());
|
||||
{
|
||||
|
@ -143,8 +135,7 @@ TEST_F(FileSystemTest, RenameWithExistingTargetFile)
|
|||
}
|
||||
|
||||
// Create the test target file and leave it empty.
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f2", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f2", 0, modes), ResultCode::Success);
|
||||
|
||||
// Rename f1 to f2 and check that f1 replaced f2.
|
||||
EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, "/tmp/f1", "/tmp/f2"), ResultCode::Success);
|
||||
|
@ -169,8 +160,7 @@ TEST_F(FileSystemTest, GetDirectoryStats)
|
|||
|
||||
check_stats(0u, 1u);
|
||||
|
||||
EXPECT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/file", 0, Mode::Read, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
EXPECT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/file", 0, modes), ResultCode::Success);
|
||||
// Still no clusters (because the file is empty), but 2 inodes now.
|
||||
check_stats(0u, 2u);
|
||||
|
||||
|
@ -204,8 +194,7 @@ TEST_F(FileSystemTest, Seek)
|
|||
{
|
||||
const std::vector<u8> TEST_DATA(10);
|
||||
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, modes), ResultCode::Success);
|
||||
|
||||
const Result<FileHandle> file = m_fs->OpenFile(Uid{0}, Gid{0}, "/tmp/f", Mode::ReadWrite);
|
||||
ASSERT_TRUE(file.Succeeded());
|
||||
|
@ -244,8 +233,7 @@ TEST_F(FileSystemTest, WriteAndSimpleReadback)
|
|||
const std::vector<u8> TEST_DATA{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
|
||||
std::vector<u8> read_buffer(TEST_DATA.size());
|
||||
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, modes), ResultCode::Success);
|
||||
|
||||
const Result<FileHandle> file = m_fs->OpenFile(Uid{0}, Gid{0}, "/tmp/f", Mode::ReadWrite);
|
||||
ASSERT_TRUE(file.Succeeded());
|
||||
|
@ -264,8 +252,7 @@ TEST_F(FileSystemTest, WriteAndRead)
|
|||
const std::vector<u8> TEST_DATA{{0xf, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
|
||||
std::vector<u8> buffer(TEST_DATA.size());
|
||||
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, modes), ResultCode::Success);
|
||||
|
||||
Result<FileHandle> tmp_handle = m_fs->OpenFile(Uid{0}, Gid{0}, "/tmp/f", Mode::ReadWrite);
|
||||
ASSERT_TRUE(tmp_handle.Succeeded());
|
||||
|
@ -298,8 +285,7 @@ TEST_F(FileSystemTest, WriteAndRead)
|
|||
|
||||
TEST_F(FileSystemTest, MultipleHandles)
|
||||
{
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, Mode::ReadWrite, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, modes), ResultCode::Success);
|
||||
|
||||
{
|
||||
const Result<FileHandle> file = m_fs->OpenFile(Uid{0}, Gid{0}, "/tmp/f", Mode::ReadWrite);
|
||||
|
@ -333,8 +319,7 @@ TEST_F(FileSystemTest, MultipleHandles)
|
|||
// If it is not a file, ResultCode::Invalid must be returned.
|
||||
TEST_F(FileSystemTest, ReadDirectoryOnFile)
|
||||
{
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, Mode::Read, Mode::None, Mode::None),
|
||||
ResultCode::Success);
|
||||
ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f", 0, modes), ResultCode::Success);
|
||||
|
||||
const Result<std::vector<std::string>> result = m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp/f");
|
||||
ASSERT_FALSE(result.Succeeded());
|
||||
|
|
Loading…
Reference in New Issue