ams: support building unit test programs on windows/linux/macos
This commit is contained in:
@@ -206,7 +206,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Setup the keyslot cache. */
|
||||
for (s32 i = 0; i < KeySlotCacheEntryCount; i++) {
|
||||
s32 slot_index;
|
||||
s32 slot_index = -1;
|
||||
R_ABORT_UNLESS(spl::AllocateAesKeySlot(std::addressof(slot_index)));
|
||||
g_key_slot_cache_entry[i].emplace(slot_index);
|
||||
g_key_slot_cache.AddEntry(std::addressof(g_key_slot_cache_entry[i].value()));
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::fssystem {
|
||||
|
||||
DirectoryRedirectionFileSystem::DirectoryRedirectionFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc)
|
||||
: PathResolutionFileSystem(fs, unc)
|
||||
{
|
||||
m_before_dir = nullptr;
|
||||
m_after_dir = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(before, after));
|
||||
}
|
||||
|
||||
DirectoryRedirectionFileSystem::DirectoryRedirectionFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc)
|
||||
: PathResolutionFileSystem(std::move(fs), unc)
|
||||
{
|
||||
m_before_dir = nullptr;
|
||||
m_after_dir = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(before, after));
|
||||
}
|
||||
|
||||
DirectoryRedirectionFileSystem::~DirectoryRedirectionFileSystem() {
|
||||
if (m_before_dir != nullptr) {
|
||||
fs::impl::Deallocate(m_before_dir, m_before_dir_len);
|
||||
}
|
||||
if (m_after_dir != nullptr) {
|
||||
fs::impl::Deallocate(m_after_dir, m_after_dir_len);
|
||||
}
|
||||
}
|
||||
|
||||
Result DirectoryRedirectionFileSystem::GetNormalizedDirectoryPath(char **out, size_t *out_size, const char *dir) {
|
||||
/* Clear output. */
|
||||
*out = nullptr;
|
||||
*out_size = 0;
|
||||
|
||||
/* Make sure the path isn't too long. */
|
||||
R_UNLESS(strnlen(dir, fs::EntryNameLengthMax + 1) <= fs::EntryNameLengthMax, fs::ResultTooLongPath());
|
||||
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 2];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, &normalized_path_len, dir, sizeof(normalized_path), this->IsUncPreserved(), false));
|
||||
|
||||
/* Ensure terminating '/' */
|
||||
if (!fs::PathNormalizer::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ASSERT(normalized_path_len + 2 < sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = fs::StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
++normalized_path_len;
|
||||
}
|
||||
|
||||
/* Allocate new path. */
|
||||
const size_t size = normalized_path_len + 1;
|
||||
char *new_dir = static_cast<char *>(fs::impl::Allocate(size));
|
||||
AMS_ABORT_UNLESS(new_dir != nullptr);
|
||||
/* TODO: custom fs::ResultAllocationFailure? */
|
||||
|
||||
/* Copy path in. */
|
||||
std::memcpy(new_dir, normalized_path, normalized_path_len);
|
||||
new_dir[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
|
||||
/* Set output. */
|
||||
*out = new_dir;
|
||||
*out_size = size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result DirectoryRedirectionFileSystem::Initialize(const char *before, const char *after) {
|
||||
/* Normalize both directories. */
|
||||
this->GetNormalizedDirectoryPath(std::addressof(m_before_dir), std::addressof(m_before_dir_len), before);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(m_after_dir), std::addressof(m_after_dir_len), after);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result DirectoryRedirectionFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(relative_path[0] == '/');
|
||||
AMS_ASSERT(m_before_dir_len >= 2);
|
||||
AMS_ASSERT(m_after_dir_len >= 2);
|
||||
AMS_ASSERT(m_after_dir_len <= out_size);
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(m_before_dir[m_before_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(m_before_dir[m_before_dir_len - 2]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(m_after_dir[m_after_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(m_after_dir[m_after_dir_len - 2]));
|
||||
|
||||
/* Normalize the relative path. */
|
||||
char normalized_rel_path[fs::EntryNameLengthMax + 1];
|
||||
size_t normalized_rel_path_len;
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_rel_path, std::addressof(normalized_rel_path_len), relative_path, sizeof(normalized_rel_path), this->IsUncPreserved(), false));
|
||||
|
||||
const bool is_prefixed = std::memcmp(normalized_rel_path, m_before_dir, m_before_dir_len - 2) == 0 &&
|
||||
(fs::PathNormalizer::IsSeparator(normalized_rel_path[m_before_dir_len - 2]) || fs::PathNormalizer::IsNullTerminator(normalized_rel_path[m_before_dir_len - 2]));
|
||||
if (is_prefixed) {
|
||||
const size_t before_prefix_len = m_before_dir_len - 2;
|
||||
const size_t after_prefix_len = m_after_dir_len - 2;
|
||||
const size_t final_str_len = after_prefix_len + normalized_rel_path_len - before_prefix_len;
|
||||
R_UNLESS(final_str_len < out_size, fs::ResultTooLongPath());
|
||||
|
||||
/* Copy normalized path. */
|
||||
std::memcpy(out, m_after_dir, after_prefix_len);
|
||||
std::memcpy(out + after_prefix_len, normalized_rel_path + before_prefix_len, normalized_rel_path_len - before_prefix_len);
|
||||
out[final_str_len] = fs::StringTraits::NullTerminator;
|
||||
} else {
|
||||
/* Path is not prefixed. */
|
||||
R_UNLESS(normalized_rel_path_len + 1 <= out_size, fs::ResultTooLongPath());
|
||||
std::memcpy(out, normalized_rel_path, normalized_rel_path_len);
|
||||
out[normalized_rel_path_len] = fs::StringTraits::NullTerminator;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,13 +19,15 @@ namespace ams::fssystem {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t IdealWorkBufferSize = 0x100000; /* 1 MiB */
|
||||
constexpr size_t IdealWorkBufferSize = 1_MB;
|
||||
constexpr size_t MinimumWorkBufferSize = 1_KB;
|
||||
|
||||
constexpr const char CommittedDirectoryPath[] = "/0/";
|
||||
constexpr const char WorkingDirectoryPath[] = "/1/";
|
||||
constexpr const char SynchronizingDirectoryPath[] = "/_/";
|
||||
constexpr const fs::Path CommittedDirectoryPath = fs::MakeConstantPath("/0");
|
||||
constexpr const fs::Path WorkingDirectoryPath = fs::MakeConstantPath("/1");
|
||||
constexpr const fs::Path SynchronizingDirectoryPath = fs::MakeConstantPath("/_");
|
||||
constexpr const fs::Path LockFilePath = fs::MakeConstantPath("/.lock");
|
||||
|
||||
class DirectorySaveDataFile : public fs::fsa::IFile {
|
||||
class DirectorySaveDataFile : public fs::fsa::IFile, public fs::impl::Newable {
|
||||
private:
|
||||
std::unique_ptr<fs::fsa::IFile> m_base_file;
|
||||
DirectorySaveDataFileSystem *m_parent_fs;
|
||||
@@ -38,7 +40,7 @@ namespace ams::fssystem {
|
||||
virtual ~DirectorySaveDataFile() {
|
||||
/* Observe closing of writable file. */
|
||||
if (m_open_mode & fs::OpenMode_Write) {
|
||||
m_parent_fs->OnWritableFileClose();
|
||||
m_parent_fs->DecrementWriteOpenFileCount();
|
||||
}
|
||||
}
|
||||
public:
|
||||
@@ -73,25 +75,14 @@ namespace ams::fssystem {
|
||||
|
||||
}
|
||||
|
||||
DirectorySaveDataFileSystem::DirectorySaveDataFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs)
|
||||
: PathResolutionFileSystem(fs), m_accessor_mutex(), m_open_writable_files(0)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
Result DirectorySaveDataFileSystem::Initialize(bool journaling_supported, bool multi_commit_supported, bool journaling_enabled) {
|
||||
/* Configure ourselves. */
|
||||
m_is_journaling_supported = journaling_supported;
|
||||
m_is_multi_commit_supported = multi_commit_supported;
|
||||
m_is_journaling_enabled = journaling_enabled;
|
||||
|
||||
DirectorySaveDataFileSystem::DirectorySaveDataFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs)
|
||||
: PathResolutionFileSystem(std::move(fs)), m_accessor_mutex(), m_open_writable_files(0)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
DirectorySaveDataFileSystem::~DirectorySaveDataFileSystem() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::Initialize() {
|
||||
/* Nintendo does not acquire the lock here, but I think we probably should. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
/* Ensure that we can initialize further by acquiring a lock on the filesystem. */
|
||||
R_TRY(this->AcquireLockFile());
|
||||
|
||||
fs::DirectoryEntryType type;
|
||||
|
||||
@@ -100,44 +91,35 @@ namespace ams::fssystem {
|
||||
/* If path isn't found, create working directory and committed directory. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(m_base_fs->CreateDirectory(WorkingDirectoryPath));
|
||||
R_TRY(m_base_fs->CreateDirectory(CommittedDirectoryPath));
|
||||
|
||||
if (m_is_journaling_supported) {
|
||||
R_TRY(m_base_fs->CreateDirectory(CommittedDirectoryPath));
|
||||
}
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Now check for the committed directory. */
|
||||
R_TRY_CATCH(m_base_fs->GetEntryType(std::addressof(type), CommittedDirectoryPath)) {
|
||||
/* Committed doesn't exist, so synchronize and rename. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath));
|
||||
R_TRY(m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath));
|
||||
return ResultSuccess();
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
/* If we support journaling, we need to set up the committed directory. */
|
||||
if (m_is_journaling_supported) {
|
||||
/* Now check for the committed directory. */
|
||||
R_TRY_CATCH(m_base_fs->GetEntryType(std::addressof(type), CommittedDirectoryPath)) {
|
||||
/* Committed doesn't exist, so synchronize and rename. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath));
|
||||
R_TRY(m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath));
|
||||
R_SUCCEED();
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* The committed directory exists, so synchronize it to the working directory. */
|
||||
return this->SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath);
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::AllocateWorkBuffer(std::unique_ptr<u8[]> *out, size_t *out_size, size_t size) {
|
||||
/* Repeatedly try to allocate until success. */
|
||||
while (size > 0x200) {
|
||||
/* Allocate the buffer. */
|
||||
if (auto mem = new (std::nothrow) u8[size]; mem != nullptr) {
|
||||
out->reset(mem);
|
||||
*out_size = size;
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
/* Divide size by two. */
|
||||
size >>= 1;
|
||||
/* The committed directory exists, so if we should, synchronize it to the working directory. */
|
||||
if (m_is_journaling_enabled) {
|
||||
R_TRY(this->SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Return a result here? Nintendo does not, but they have other allocation failed results. */
|
||||
/* Consider returning fs::ResultFsAllocationFailureInDirectorySaveDataFileSystem? */
|
||||
AMS_ABORT_UNLESS(false);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::SynchronizeDirectory(const char *dst, const char *src) {
|
||||
Result DirectorySaveDataFileSystem::SynchronizeDirectory(const fs::Path &dst, const fs::Path &src) {
|
||||
/* Delete destination dir and recreate it. */
|
||||
R_TRY_CATCH(m_base_fs->DeleteDirectoryRecursively(dst)) {
|
||||
R_CATCH(fs::ResultPathNotFound) { /* Nintendo returns error unconditionally, but I think that's a bug in their code. */}
|
||||
@@ -146,132 +128,239 @@ namespace ams::fssystem {
|
||||
R_TRY(m_base_fs->CreateDirectory(dst));
|
||||
|
||||
/* Get a work buffer to work with. */
|
||||
std::unique_ptr<u8[]> work_buf;
|
||||
size_t work_buf_size;
|
||||
R_TRY(this->AllocateWorkBuffer(std::addressof(work_buf), std::addressof(work_buf_size), IdealWorkBufferSize));
|
||||
fssystem::PooledBuffer buffer;
|
||||
buffer.AllocateParticularlyLarge(IdealWorkBufferSize, MinimumWorkBufferSize);
|
||||
|
||||
/* Copy the directory recursively. */
|
||||
return fssystem::CopyDirectoryRecursively(m_base_fs, dst, src, work_buf.get(), work_buf_size);
|
||||
fs::DirectoryEntry dir_entry_buffer = {};
|
||||
R_RETURN(fssystem::CopyDirectoryRecursively(m_base_fs, dst, src, std::addressof(dir_entry_buffer), buffer.GetBuffer(), buffer.GetSize()));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
R_UNLESS(strnlen(relative_path, fs::EntryNameLengthMax + 1) < fs::EntryNameLengthMax + 1, fs::ResultTooLongPath());
|
||||
R_UNLESS(fs::PathNormalizer::IsSeparator(relative_path[0]), fs::ResultInvalidPath());
|
||||
|
||||
/* Copy working directory path. */
|
||||
std::strncpy(out, WorkingDirectoryPath, out_size);
|
||||
out[out_size - 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
/* Normalize it. */
|
||||
constexpr size_t WorkingDirectoryPathLength = sizeof(WorkingDirectoryPath) - 1;
|
||||
size_t normalized_length;
|
||||
return fs::PathNormalizer::Normalize(out + WorkingDirectoryPathLength - 1, std::addressof(normalized_length), relative_path, out_size - (WorkingDirectoryPathLength - 1));
|
||||
Result DirectorySaveDataFileSystem::ResolvePath(fs::Path *out, const fs::Path &path) {
|
||||
const fs::Path &directory = (m_is_journaling_supported && !m_is_journaling_enabled) ? CommittedDirectoryPath : WorkingDirectoryPath;
|
||||
R_RETURN(out->Combine(directory, path));
|
||||
}
|
||||
|
||||
void DirectorySaveDataFileSystem::OnWritableFileClose() {
|
||||
Result DirectorySaveDataFileSystem::AcquireLockFile() {
|
||||
/* If we already have a lock file, we don't need to lock again. */
|
||||
R_SUCCEED_IF(m_lock_file != nullptr);
|
||||
|
||||
/* Open the lock file. */
|
||||
std::unique_ptr<fs::fsa::IFile> file;
|
||||
R_TRY_CATCH(m_base_fs->OpenFile(std::addressof(file), LockFilePath, fs::OpenMode_ReadWrite)) {
|
||||
/* If the lock file doesn't yet exist, we may need to create it. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(m_base_fs->CreateFile(LockFilePath, 0));
|
||||
R_TRY(m_base_fs->OpenFile(std::addressof(file), LockFilePath, fs::OpenMode_ReadWrite));
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Set our lock file. */
|
||||
m_lock_file = std::move(file);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void DirectorySaveDataFileSystem::DecrementWriteOpenFileCount() {
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
m_open_writable_files--;
|
||||
|
||||
/* Nintendo does not check this, but I think it's sensible to do so. */
|
||||
AMS_ABORT_UNLESS(m_open_writable_files >= 0);
|
||||
--m_open_writable_files;
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::CopySaveFromFileSystem(fs::fsa::IFileSystem *save_fs) {
|
||||
/* If the input save is null, there's nothing to copy. */
|
||||
R_SUCCEED_IF(save_fs == nullptr);
|
||||
|
||||
/* Get a work buffer to work with. */
|
||||
std::unique_ptr<u8[]> work_buf;
|
||||
size_t work_buf_size;
|
||||
R_TRY(this->AllocateWorkBuffer(std::addressof(work_buf), std::addressof(work_buf_size), IdealWorkBufferSize));
|
||||
|
||||
/* Copy the directory recursively. */
|
||||
R_TRY(fssystem::CopyDirectoryRecursively(m_base_fs, save_fs, fs::PathNormalizer::RootPath, fs::PathNormalizer::RootPath, work_buf.get(), work_buf_size));
|
||||
|
||||
return this->Commit();
|
||||
}
|
||||
|
||||
/* Overridden from IPathResolutionFileSystem */
|
||||
Result DirectorySaveDataFileSystem::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(this->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
Result DirectorySaveDataFileSystem::DoCreateFile(const fs::Path &path, s64 size, int option) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->CreateFile(resolved, size, option));
|
||||
}
|
||||
Result DirectorySaveDataFileSystem::DoDeleteFile(const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->DeleteFile(resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoCreateDirectory(const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->CreateDirectory(resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoDeleteDirectory(const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->DeleteDirectory(resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoDeleteDirectoryRecursively(const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->DeleteDirectoryRecursively(resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
/* Resolve the final paths. */
|
||||
fs::Path old_resolved;
|
||||
fs::Path new_resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(old_resolved), old_path));
|
||||
R_TRY(this->ResolvePath(std::addressof(new_resolved), new_path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->RenameFile(old_resolved, new_resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
/* Resolve the final paths. */
|
||||
fs::Path old_resolved;
|
||||
fs::Path new_resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(old_resolved), old_path));
|
||||
R_TRY(this->ResolvePath(std::addressof(new_resolved), new_path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->RenameDirectory(old_resolved, new_resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->GetEntryType(out, resolved));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
/* Open base file. */
|
||||
std::unique_ptr<fs::fsa::IFile> base_file;
|
||||
R_TRY(m_base_fs->OpenFile(std::addressof(base_file), full_path, mode));
|
||||
R_TRY(m_base_fs->OpenFile(std::addressof(base_file), resolved, mode));
|
||||
|
||||
std::unique_ptr<DirectorySaveDataFile> file(new (std::nothrow) DirectorySaveDataFile(std::move(base_file), this, mode));
|
||||
/* Make DirectorySaveDataFile. */
|
||||
std::unique_ptr<fs::fsa::IFile> file = std::make_unique<DirectorySaveDataFile>(std::move(base_file), this, mode);
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInDirectorySaveDataFileSystem());
|
||||
|
||||
/* Increment our open writable files, if the file is writable. */
|
||||
if (mode & fs::OpenMode_Write) {
|
||||
m_open_writable_files++;
|
||||
++m_open_writable_files;
|
||||
}
|
||||
|
||||
/* Set the output. */
|
||||
*out_file = std::move(file);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->OpenDirectory(out_dir, resolved, mode));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoCommit() {
|
||||
/* Here, Nintendo does the following (with retries): */
|
||||
/* - Rename Committed -> Synchronizing. */
|
||||
/* - Synchronize Working -> Synchronizing (deleting Synchronizing). */
|
||||
/* - Rename Synchronizing -> Committed. */
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_UNLESS(m_open_writable_files == 0, fs::ResultPreconditionViolation());
|
||||
/* If we aren't journaling, we don't need to do anything. */
|
||||
R_SUCCEED_IF(!m_is_journaling_enabled);
|
||||
R_SUCCEED_IF(!m_is_journaling_supported);
|
||||
|
||||
const auto RenameCommitedDir = [&]() { return m_base_fs->RenameDirectory(CommittedDirectoryPath, SynchronizingDirectoryPath); };
|
||||
const auto SynchronizeWorkingDir = [&]() { return this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath); };
|
||||
const auto RenameSynchronizingDir = [&]() { return m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); };
|
||||
/* Check that there are no open files blocking the commit. */
|
||||
R_UNLESS(m_open_writable_files == 0, fs::ResultWriteModeFileNotClosed());
|
||||
|
||||
/* Rename Committed -> Synchronizing. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked(std::move(RenameCommitedDir)));
|
||||
/* Remove the previous commit by renaming the folder. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked([&] () ALWAYS_INLINE_LAMBDA { R_RETURN(m_base_fs->RenameDirectory(CommittedDirectoryPath, SynchronizingDirectoryPath)); }));
|
||||
|
||||
/* - Synchronize Working -> Synchronizing (deleting Synchronizing). */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked(std::move(SynchronizeWorkingDir)));
|
||||
/* Synchronize the working directory to the synchronizing directory. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked([&] () ALWAYS_INLINE_LAMBDA { R_RETURN(this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath)); }));
|
||||
|
||||
/* - Rename Synchronizing -> Committed. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked(std::move(RenameSynchronizingDir)));
|
||||
/* Rename the synchronized directory to commit it. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked([&] () ALWAYS_INLINE_LAMBDA { R_RETURN(m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath)); }));
|
||||
|
||||
/* TODO: Should I call m_base_fs->Commit()? Nintendo does not. */
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoGetFreeSpaceSize(s64 *out, const fs::Path &path) {
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
/* Get the free space size in our working directory. */
|
||||
AMS_UNUSED(path);
|
||||
R_RETURN(m_base_fs->GetFreeSpaceSize(out, WorkingDirectoryPath));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoGetTotalSpaceSize(s64 *out, const fs::Path &path) {
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
/* Get the free space size in our working directory. */
|
||||
AMS_UNUSED(path);
|
||||
R_RETURN(m_base_fs->GetTotalSpaceSize(out, WorkingDirectoryPath));
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoCleanDirectoryRecursively(const fs::Path &path) {
|
||||
/* Resolve the final path. */
|
||||
fs::Path resolved;
|
||||
R_TRY(this->ResolvePath(std::addressof(resolved), path));
|
||||
|
||||
/* Lock ourselves. */
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_RETURN(m_base_fs->CleanDirectoryRecursively(resolved));
|
||||
}
|
||||
|
||||
/* Overridden from IPathResolutionFileSystem but not commands. */
|
||||
Result DirectorySaveDataFileSystem::DoCommitProvisionally(s64 counter) {
|
||||
/* Nintendo does nothing here. */
|
||||
/* Check that we support multi-commit. */
|
||||
R_UNLESS(m_is_multi_commit_supported, fs::ResultUnsupportedOperationInDirectorySaveDataFileSystemA());
|
||||
|
||||
/* Do nothing. */
|
||||
AMS_UNUSED(counter);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoRollback() {
|
||||
/* Initialize overwrites the working directory with the committed directory. */
|
||||
return this->Initialize();
|
||||
}
|
||||
/* On non-journaled savedata, there's nothing to roll back to. */
|
||||
R_SUCCEED_IF(!m_is_journaling_supported);
|
||||
|
||||
/* Explicitly overridden to be not implemented. */
|
||||
Result DirectorySaveDataFileSystem::DoGetFreeSpaceSize(s64 *out, const char *path) {
|
||||
AMS_UNUSED(out, path);
|
||||
return fs::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoGetTotalSpaceSize(s64 *out, const char *path) {
|
||||
AMS_UNUSED(out, path);
|
||||
return fs::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const char *path) {
|
||||
AMS_UNUSED(out, path);
|
||||
return fs::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const char *path) {
|
||||
AMS_UNUSED(dst, dst_size, src, src_size, query, path);
|
||||
return fs::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::DoFlush() {
|
||||
return fs::ResultNotImplemented();
|
||||
/* Perform a re-initialize. */
|
||||
R_RETURN(this->Initialize(m_is_journaling_supported, m_is_multi_commit_supported, m_is_journaling_enabled));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
namespace ams::fssystem {
|
||||
|
||||
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||
namespace {
|
||||
|
||||
constexpr inline size_t MaxExternalCodeFileSystem = 0x10;
|
||||
@@ -72,5 +73,21 @@ namespace ams::fssystem {
|
||||
g_hnd_map.Remove(program_id);
|
||||
}
|
||||
}
|
||||
#else
|
||||
fs::fsa::IFileSystem *GetExternalCodeFileSystem(ncm::ProgramId program_id) {
|
||||
AMS_UNUSED(program_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Result CreateExternalCode(os::NativeHandle *out, ncm::ProgramId program_id) {
|
||||
AMS_UNUSED(out, program_id);
|
||||
R_THROW(fs::ResultNotImplemented());
|
||||
}
|
||||
|
||||
void DestroyExternalCode(ncm::ProgramId program_id) {
|
||||
AMS_UNUSED(program_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ namespace ams::fssystem {
|
||||
constexpr size_t MaxCacheCount = 1024;
|
||||
constexpr size_t BlockSize = 16_KB;
|
||||
|
||||
alignas(os::MemoryPageSize) u8 g_exp_heap_buffer[ExpHeapSize];
|
||||
lmem::HeapHandle g_exp_heap_handle = nullptr;
|
||||
fssrv::PeakCheckableMemoryResourceFromExpHeap g_exp_allocator(ExpHeapSize);
|
||||
alignas(os::MemoryPageSize) constinit u8 g_exp_heap_buffer[ExpHeapSize];
|
||||
constinit lmem::HeapHandle g_exp_heap_handle = nullptr;
|
||||
constinit fssrv::PeakCheckableMemoryResourceFromExpHeap g_exp_allocator(ExpHeapSize);
|
||||
|
||||
void InitializeExpHeap() {
|
||||
if (g_exp_heap_handle == nullptr) {
|
||||
@@ -70,25 +70,25 @@ namespace ams::fssystem {
|
||||
lmem::FreeToExpHeap(g_exp_heap_handle, p);
|
||||
}
|
||||
|
||||
alignas(os::MemoryPageSize) u8 g_device_buffer[DeviceBufferSize];
|
||||
alignas(os::MemoryPageSize) constinit u8 g_device_buffer[DeviceBufferSize] = {};
|
||||
|
||||
alignas(os::MemoryPageSize) u8 g_buffer_pool[BufferPoolSize];
|
||||
alignas(os::MemoryPageSize) constinit u8 g_buffer_pool[BufferPoolSize] = {};
|
||||
|
||||
util::TypedStorage<mem::StandardAllocator> g_buffer_allocator;
|
||||
util::TypedStorage<fssrv::MemoryResourceFromStandardAllocator> g_allocator;
|
||||
constinit util::TypedStorage<mem::StandardAllocator> g_buffer_allocator = {};
|
||||
constinit util::TypedStorage<fssrv::MemoryResourceFromStandardAllocator> g_allocator = {};
|
||||
|
||||
/* TODO: Nintendo uses os::SetMemoryHeapSize (svc::SetHeapSize) and os::AllocateMemoryBlock for the BufferManager heap. */
|
||||
/* It's unclear how we should handle this in ams.mitm (especially hoping to reuse some logic for fs reimpl). */
|
||||
/* Should we be doing the same(?) */
|
||||
util::TypedStorage<fssystem::FileSystemBufferManager> g_buffer_manager;
|
||||
alignas(os::MemoryPageSize) u8 g_buffer_manager_heap[BufferManagerHeapSize];
|
||||
constinit util::TypedStorage<fssystem::FileSystemBufferManager> g_buffer_manager = {};
|
||||
alignas(os::MemoryPageSize) constinit u8 g_buffer_manager_heap[BufferManagerHeapSize] = {};
|
||||
|
||||
/* FileSystem creators. */
|
||||
util::TypedStorage<fssrv::fscreator::RomFileSystemCreator> g_rom_fs_creator;
|
||||
util::TypedStorage<fssrv::fscreator::PartitionFileSystemCreator> g_partition_fs_creator;
|
||||
util::TypedStorage<fssrv::fscreator::StorageOnNcaCreator> g_storage_on_nca_creator;
|
||||
constinit util::TypedStorage<fssrv::fscreator::RomFileSystemCreator> g_rom_fs_creator = {};
|
||||
constinit util::TypedStorage<fssrv::fscreator::PartitionFileSystemCreator> g_partition_fs_creator = {};
|
||||
constinit util::TypedStorage<fssrv::fscreator::StorageOnNcaCreator> g_storage_on_nca_creator = {};
|
||||
|
||||
fssrv::fscreator::FileSystemCreatorInterfaces g_fs_creator_interfaces = {};
|
||||
constinit fssrv::fscreator::FileSystemCreatorInterfaces g_fs_creator_interfaces = {};
|
||||
|
||||
}
|
||||
|
||||
@@ -162,7 +162,21 @@ namespace ams::fssystem {
|
||||
/* TODO FS-REIMPL: Sd Card detection, speed emulation. */
|
||||
|
||||
/* Initialize fssrv. TODO FS-REIMPL: More arguments, more actions taken. */
|
||||
fssrv::InitializeForFileSystemProxy(std::addressof(g_fs_creator_interfaces), GetPointer(g_buffer_manager), is_development_function_enabled);
|
||||
const fssrv::FileSystemProxyConfiguration config = {
|
||||
.m_fs_creator_interfaces = std::addressof(g_fs_creator_interfaces),
|
||||
.m_base_storage_service_impl = nullptr /* TODO */,
|
||||
.m_base_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_nca_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_save_data_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_access_failure_management_service_impl = nullptr /* TODO */,
|
||||
.m_time_service_impl = nullptr /* TODO */,
|
||||
.m_status_report_service_impl = nullptr /* TODO */,
|
||||
.m_program_registry_service_impl = std::addressof(program_registry_service),
|
||||
.m_access_log_service_impl = nullptr /* TODO */,
|
||||
.m_debug_configuration_service_impl = nullptr /* TODO */,
|
||||
};
|
||||
|
||||
fssrv::InitializeForFileSystemProxy(config);
|
||||
|
||||
/* TODO FS-REIMPL: GetFileSystemProxyServiceObject(), set current process, initialize global service object. */
|
||||
|
||||
@@ -241,7 +255,21 @@ namespace ams::fssystem {
|
||||
};
|
||||
|
||||
/* Initialize fssrv. TODO FS-REIMPL: More arguments, more actions taken. */
|
||||
fssrv::InitializeForFileSystemProxy(std::addressof(g_fs_creator_interfaces), GetPointer(g_buffer_manager), is_development_function_enabled);
|
||||
const fssrv::FileSystemProxyConfiguration config = {
|
||||
.m_fs_creator_interfaces = std::addressof(g_fs_creator_interfaces),
|
||||
.m_base_storage_service_impl = nullptr /* TODO */,
|
||||
.m_base_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_nca_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_save_data_file_system_service_impl = nullptr /* TODO */,
|
||||
.m_access_failure_management_service_impl = nullptr /* TODO */,
|
||||
.m_time_service_impl = nullptr /* TODO */,
|
||||
.m_status_report_service_impl = nullptr /* TODO */,
|
||||
.m_program_registry_service_impl = nullptr /* TODO */,
|
||||
.m_access_log_service_impl = nullptr /* TODO */,
|
||||
.m_debug_configuration_service_impl = nullptr /* TODO */,
|
||||
};
|
||||
|
||||
fssrv::InitializeForFileSystemProxy(config);
|
||||
|
||||
/* Disable auto-abort in fs library code. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -292,13 +292,13 @@ namespace ams::fssystem {
|
||||
using IntegrityLevelInfo = NcaFsHeader::HashData::IntegrityMetaInfo::LevelHashInfo;
|
||||
using IntegrityDataInfo = IntegrityLevelInfo::HierarchicalIntegrityVerificationLevelInformation;
|
||||
|
||||
inline const Sha256DataRegion &GetSha256DataRegion(const NcaFsHeader::HashData &hash_data) {
|
||||
return hash_data.hierarchical_sha256_data.hash_layer_region[1];
|
||||
}
|
||||
// inline const Sha256DataRegion &GetSha256DataRegion(const NcaFsHeader::HashData &hash_data) {
|
||||
// return hash_data.hierarchical_sha256_data.hash_layer_region[1];
|
||||
// }
|
||||
|
||||
inline const IntegrityDataInfo &GetIntegrityDataInfo(const NcaFsHeader::HashData &hash_data) {
|
||||
return hash_data.integrity_meta_info.level_hash_info.info[hash_data.integrity_meta_info.level_hash_info.max_layers - 2];
|
||||
}
|
||||
// inline const IntegrityDataInfo &GetIntegrityDataInfo(const NcaFsHeader::HashData &hash_data) {
|
||||
// return hash_data.integrity_meta_info.level_hash_info.info[hash_data.integrity_meta_info.level_hash_info.max_layers - 2];
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ namespace ams::fssystem {
|
||||
Result NcaFileSystemDriver::CreateSparseStorage(std::shared_ptr<fs::IStorage> *out, s64 *out_fs_data_offset, std::shared_ptr<fssystem::SparseStorage> *out_sparse_storage, std::shared_ptr<fs::IStorage> *out_meta_storage, s32 index, const NcaAesCtrUpperIv &upper_iv, const NcaSparseInfo &sparse_info) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(base_storage != nullptr);
|
||||
AMS_ASSERT(out_fs_data_offset != nullptr);
|
||||
|
||||
/* Check the sparse info generation. */
|
||||
R_UNLESS(sparse_info.generation != 0, fs::ResultInvalidNcaHeader());
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Generate the hash. */
|
||||
Hash hash;
|
||||
crypto::GenerateSha256Hash(std::addressof(hash), sizeof(hash), std::addressof(m_data), sizeof(NcaFsHeader));
|
||||
crypto::GenerateSha256(std::addressof(hash), sizeof(hash), std::addressof(m_data), sizeof(NcaFsHeader));
|
||||
|
||||
/* Validate the hash. */
|
||||
R_UNLESS(crypto::IsSameBytes(std::addressof(reader.GetFsHeaderHash(index)), std::addressof(hash), sizeof(Hash)), fs::ResultNcaFsHeaderHashVerificationFailed());
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace ams::fssystem {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char RootPath[] = "/";
|
||||
|
||||
class PartitionFileSystemDefaultAllocator : public MemoryResource {
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
@@ -53,7 +55,7 @@ namespace ams::fssystem {
|
||||
|
||||
virtual Result DoGetSize(s64 *out) override final {
|
||||
*out = m_partition_entry->size;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoFlush() override final {
|
||||
@@ -61,7 +63,7 @@ namespace ams::fssystem {
|
||||
R_SUCCEED_IF((m_mode & fs::OpenMode_Write) == 0);
|
||||
|
||||
/* Flush base storage. */
|
||||
return m_parent->m_base_storage->Flush();
|
||||
R_RETURN(m_parent->m_base_storage->Flush());
|
||||
}
|
||||
|
||||
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
|
||||
@@ -78,12 +80,12 @@ namespace ams::fssystem {
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(m_partition_entry->size), fs::ResultInvalidSize());
|
||||
|
||||
/* Write to the base storage. */
|
||||
return m_parent->m_base_storage->Write(m_parent->m_meta_data_size + m_partition_entry->offset + offset, buffer, size);
|
||||
R_RETURN(m_parent->m_base_storage->Write(m_parent->m_meta_data_size + m_partition_entry->offset + offset, buffer, size));
|
||||
}
|
||||
|
||||
virtual Result DoSetSize(s64 size) override final {
|
||||
R_TRY(this->DrySetSize(size, m_mode));
|
||||
return fs::ResultUnsupportedOperationInPartitionFileA();
|
||||
R_RETURN(fs::ResultUnsupportedOperationInPartitionFileA());
|
||||
}
|
||||
|
||||
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
|
||||
@@ -96,7 +98,7 @@ namespace ams::fssystem {
|
||||
case fs::OperationId::QueryRange:
|
||||
break;
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInPartitionFileB();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileB());
|
||||
}
|
||||
|
||||
/* Validate offset and size. */
|
||||
@@ -105,7 +107,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(m_partition_entry->size), fs::ResultInvalidSize());
|
||||
R_UNLESS(static_cast<s64>(offset + size) >= offset, fs::ResultInvalidSize());
|
||||
|
||||
return m_parent->m_base_storage->OperateRange(dst, dst_size, op_id, m_parent->m_meta_data_size + m_partition_entry->offset + offset, size, src, src_size);
|
||||
R_RETURN(m_parent->m_base_storage->OperateRange(dst, dst_size, op_id, m_parent->m_meta_data_size + m_partition_entry->offset + offset, size, src, src_size));
|
||||
}
|
||||
public:
|
||||
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
|
||||
@@ -125,7 +127,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Set output size. */
|
||||
*out = read_size;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -213,7 +215,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Set output size. */
|
||||
*out = read_size;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
@@ -229,7 +231,7 @@ namespace ams::fssystem {
|
||||
/* There are no subdirectories. */
|
||||
if ((m_mode & fs::OpenDirectoryMode_File) == 0) {
|
||||
*out_count = 0;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* Calculate number of entries. */
|
||||
@@ -247,7 +249,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
*out_count = entry_count;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoGetEntryCount(s64 *out) override final {
|
||||
@@ -258,7 +260,7 @@ namespace ams::fssystem {
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
|
||||
@@ -294,13 +296,13 @@ namespace ams::fssystem {
|
||||
m_base_storage = base_storage;
|
||||
m_meta_data_size = m_meta_data->GetMetaDataSize();
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::unique_ptr<MetaType> &&meta_data, std::shared_ptr<fs::IStorage> base_storage) {
|
||||
m_unique_meta_data = std::move(meta_data);
|
||||
return this->Initialize(m_unique_meta_data.get(), base_storage);
|
||||
R_RETURN(this->Initialize(m_unique_meta_data.get(), base_storage));
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
@@ -314,24 +316,24 @@ namespace ams::fssystem {
|
||||
m_meta_data = meta_data;
|
||||
m_meta_data_size = m_meta_data->GetMetaDataSize();
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(fs::IStorage *base_storage) {
|
||||
return this->Initialize(base_storage, std::addressof(g_partition_filesystem_default_allocator));
|
||||
R_RETURN(this->Initialize(base_storage, std::addressof(g_partition_filesystem_default_allocator)));
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::shared_ptr<fs::IStorage> base_storage) {
|
||||
m_shared_storage = std::move(base_storage);
|
||||
return this->Initialize(m_shared_storage.get());
|
||||
R_RETURN(this->Initialize(m_shared_storage.get()));
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::shared_ptr<fs::IStorage> base_storage, MemoryResource *allocator) {
|
||||
m_shared_storage = std::move(base_storage);
|
||||
return this->Initialize(m_shared_storage.get(), allocator);
|
||||
R_RETURN(this->Initialize(m_shared_storage.get(), allocator));
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
@@ -345,114 +347,116 @@ namespace ams::fssystem {
|
||||
|
||||
/* Output offset. */
|
||||
*out_offset = m_meta_data_size + m_meta_data->GetEntry(entry_index)->offset;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoGetEntryType(fs::DirectoryEntryType *out, const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(fs::PathNormalizer::IsSeparator(path[0]), fs::ResultInvalidPathFormat());
|
||||
|
||||
const char * const p = path.GetString();
|
||||
R_UNLESS(p[0] == RootPath[0], fs::ResultInvalidPathFormat());
|
||||
|
||||
/* Check if the path is for a directory. */
|
||||
if (std::strncmp(path, fs::PathNormalizer::RootPath, sizeof(fs::PathNormalizer::RootPath)) == 0) {
|
||||
if (util::Strncmp(p, RootPath, sizeof(RootPath))) {
|
||||
*out = fs::DirectoryEntryType_Directory;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* Ensure that path is for a file. */
|
||||
R_UNLESS(m_meta_data->GetEntryIndex(path + 1) >= 0, fs::ResultPathNotFound());
|
||||
R_UNLESS(m_meta_data->GetEntryIndex(p + 1) >= 0, fs::ResultPathNotFound());
|
||||
|
||||
*out = fs::DirectoryEntryType_File;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Obtain and validate the entry index. */
|
||||
const s32 entry_index = m_meta_data->GetEntryIndex(path + 1);
|
||||
const s32 entry_index = m_meta_data->GetEntryIndex(path.GetString() + 1);
|
||||
R_UNLESS(entry_index >= 0, fs::ResultPathNotFound());
|
||||
|
||||
/* Create and output the file directory. */
|
||||
std::unique_ptr file = std::make_unique<PartitionFile>(this, m_meta_data->GetEntry(entry_index), mode);
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInPartitionFileSystemB());
|
||||
*out_file = std::move(file);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(std::strncmp(path, fs::PathNormalizer::RootPath, sizeof(fs::PathNormalizer::RootPath)) == 0, fs::ResultPathNotFound());
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(path == RootPath, fs::ResultPathNotFound());
|
||||
|
||||
/* Create and output the partition directory. */
|
||||
std::unique_ptr directory = std::make_unique<PartitionDirectory>(this, mode);
|
||||
R_UNLESS(directory != nullptr, fs::ResultAllocationFailureInPartitionFileSystemC());
|
||||
*out_dir = std::move(directory);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoCommit() {
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoCleanDirectoryRecursively(const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoCleanDirectoryRecursively(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoCreateDirectory(const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoCreateDirectory(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoCreateFile(const char *path, s64 size, int option) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoCreateFile(const fs::Path &path, s64 size, int option) {
|
||||
AMS_UNUSED(path, size, option);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteDirectory(const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteDirectory(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteDirectoryRecursively(const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteDirectoryRecursively(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteFile(const char *path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoDeleteFile(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoRenameDirectory(const char *old_path, const char *new_path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
AMS_UNUSED(old_path, new_path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoRenameFile(const char *old_path, const char *new_path) {
|
||||
Result PartitionFileSystemCore<MetaType>::DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
AMS_UNUSED(old_path, new_path);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemA());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoCommitProvisionally(s64 counter) {
|
||||
AMS_UNUSED(counter);
|
||||
return fs::ResultUnsupportedOperationInPartitionFileSystemB();
|
||||
R_THROW(fs::ResultUnsupportedOperationInPartitionFileSystemB());
|
||||
}
|
||||
|
||||
template class PartitionFileSystemCore<PartitionFileSystemMeta>;
|
||||
|
||||
@@ -37,26 +37,26 @@ namespace ams::fssystem {
|
||||
virtual ~RomFsFile() { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, size, option, fs::OpenMode_Read));
|
||||
|
||||
R_TRY(m_parent->GetBaseStorage()->Read(offset + m_start, buffer, read_size));
|
||||
*out = read_size;
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoGetSize(s64 *out) override {
|
||||
*out = this->GetSize();
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoFlush() override {
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override {
|
||||
@@ -66,12 +66,12 @@ namespace ams::fssystem {
|
||||
R_TRY(this->DryWrite(std::addressof(needs_append), offset, size, option, fs::OpenMode_Read));
|
||||
AMS_ASSERT(needs_append == false);
|
||||
|
||||
return fs::ResultUnsupportedOperationInRomFsFileA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileA());
|
||||
}
|
||||
|
||||
virtual Result DoSetSize(s64 size) override {
|
||||
R_TRY(this->DrySetSize(size, fs::OpenMode_Read));
|
||||
return fs::ResultUnsupportedOperationInRomFsFileA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileA());
|
||||
}
|
||||
|
||||
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
|
||||
@@ -87,14 +87,14 @@ namespace ams::fssystem {
|
||||
operate_size = this->GetSize() - offset;
|
||||
}
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY(m_parent->GetBaseStorage()->OperateRange(dst, dst_size, op_id, m_start + offset, operate_size, src, src_size));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInRomFsFileB();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileB());
|
||||
}
|
||||
}
|
||||
public:
|
||||
@@ -115,21 +115,21 @@ namespace ams::fssystem {
|
||||
RomFsDirectory(RomFsFileSystem *p, const FindPosition &f, fs::OpenDirectoryMode m) : m_parent(p), m_current_find(f), m_first_find(f), m_mode(m) { /* ... */ }
|
||||
virtual ~RomFsDirectory() override { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(s64 *out_count, fs::DirectoryEntry *out_entries, s64 max_entries) {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
return this->ReadInternal(out_count, std::addressof(m_current_find), out_entries, max_entries);
|
||||
virtual Result DoRead(s64 *out_count, fs::DirectoryEntry *out_entries, s64 max_entries) override {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_RETURN(this->ReadInternal(out_count, std::addressof(m_current_find), out_entries, max_entries));
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
virtual Result DoGetEntryCount(s64 *out) {
|
||||
virtual Result DoGetEntryCount(s64 *out) override {
|
||||
FindPosition find = m_first_find;
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY(this->ReadInternal(out, std::addressof(find), nullptr, 0));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
private:
|
||||
Result ReadInternal(s64 *out_count, FindPosition *find, fs::DirectoryEntry *out_entries, s64 max_entries) {
|
||||
@@ -179,7 +179,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
*out_count = i;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
public:
|
||||
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
|
||||
@@ -211,11 +211,11 @@ namespace ams::fssystem {
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY(storage->Read(0, std::addressof(header), sizeof(header)));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
*out = CalculateRequiredWorkingMemorySize(header);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::Initialize(fs::IStorage *base, void *work, size_t work_size, bool use_cache) {
|
||||
@@ -272,93 +272,99 @@ namespace ams::fssystem {
|
||||
/* Set members. */
|
||||
m_entry_size = header.body_offset;
|
||||
m_base_storage = base;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::Initialize(std::shared_ptr<fs::IStorage> base, void *work, size_t work_size, bool use_cache) {
|
||||
m_shared_storage = std::move(base);
|
||||
return this->Initialize(m_shared_storage.get(), work, work_size, use_cache);
|
||||
R_RETURN(this->Initialize(m_shared_storage.get(), work, work_size, use_cache));
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetFileInfo(RomFileTable::FileInfo *out, const char *path) {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY_CATCH(m_rom_file_table.OpenFile(out, path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound());
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound());
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetFileBaseOffset(s64 *out, const char *path) {
|
||||
Result RomFsFileSystem::GetFileBaseOffset(s64 *out, const fs::Path &path) {
|
||||
R_TRY(this->CheckPathFormat(path));
|
||||
|
||||
RomFileTable::FileInfo info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(info), path));
|
||||
*out = m_entry_size + info.offset.Get();
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoCreateFile(const char *path, s64 size, int flags) {
|
||||
Result RomFsFileSystem::DoCreateFile(const fs::Path &path, s64 size, int flags) {
|
||||
AMS_UNUSED(path, size, flags);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoDeleteFile(const char *path) {
|
||||
Result RomFsFileSystem::DoDeleteFile(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoCreateDirectory(const char *path) {
|
||||
Result RomFsFileSystem::DoCreateDirectory(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoDeleteDirectory(const char *path) {
|
||||
Result RomFsFileSystem::DoDeleteDirectory(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoDeleteDirectoryRecursively(const char *path) {
|
||||
Result RomFsFileSystem::DoDeleteDirectoryRecursively(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoRenameFile(const char *old_path, const char *new_path) {
|
||||
Result RomFsFileSystem::DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
AMS_UNUSED(old_path, new_path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoRenameDirectory(const char *old_path, const char *new_path) {
|
||||
Result RomFsFileSystem::DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) {
|
||||
AMS_UNUSED(old_path, new_path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoGetEntryType(fs::DirectoryEntryType *out, const char *path) {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
Result RomFsFileSystem::DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) {
|
||||
R_TRY(this->CheckPathFormat(path));
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
fs::RomDirectoryInfo dir_info;
|
||||
|
||||
R_TRY_CATCH(m_rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path.GetString())) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
R_CATCH(fs::ResultDbmInvalidOperation) {
|
||||
RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(file_info), path));
|
||||
|
||||
*out = fs::DirectoryEntryType_File;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
*out = fs::DirectoryEntryType_Directory;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) {
|
||||
Result RomFsFileSystem::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) {
|
||||
R_UNLESS(mode == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
|
||||
|
||||
R_TRY(this->CheckPathFormat(path));
|
||||
|
||||
RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(file_info), path));
|
||||
|
||||
@@ -366,45 +372,47 @@ namespace ams::fssystem {
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInRomFsFileSystemC());
|
||||
|
||||
*out_file = std::move(file);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) {
|
||||
Result RomFsFileSystem::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) {
|
||||
R_TRY(this->CheckPathFormat(path));
|
||||
|
||||
RomFileTable::FindPosition find;
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY_CATCH(m_rom_file_table.FindOpen(std::addressof(find), path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
R_TRY_CATCH(m_rom_file_table.FindOpen(std::addressof(find), path.GetString())) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
auto dir = std::make_unique<RomFsDirectory>(this, find, mode);
|
||||
R_UNLESS(dir != nullptr, fs::ResultAllocationFailureInRomFsFileSystemD());
|
||||
|
||||
*out_dir = std::move(dir);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoCommit() {
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoGetFreeSpaceSize(s64 *out, const char *path) {
|
||||
Result RomFsFileSystem::DoGetFreeSpaceSize(s64 *out, const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
|
||||
*out = 0;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoCleanDirectoryRecursively(const char *path) {
|
||||
Result RomFsFileSystem::DoCleanDirectoryRecursively(const fs::Path &path) {
|
||||
AMS_UNUSED(path);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemA();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemA());
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::DoCommitProvisionally(s64 counter) {
|
||||
AMS_UNUSED(counter);
|
||||
return fs::ResultUnsupportedOperationInRomFsFileSystemB();
|
||||
R_THROW(fs::ResultUnsupportedOperationInRomFsFileSystemB());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::fssystem {
|
||||
|
||||
SubDirectoryFileSystem::SubDirectoryFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc)
|
||||
: PathResolutionFileSystem(fs, unc)
|
||||
{
|
||||
m_base_path = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(bp));
|
||||
}
|
||||
|
||||
SubDirectoryFileSystem::SubDirectoryFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc)
|
||||
: PathResolutionFileSystem(std::move(fs), unc)
|
||||
{
|
||||
m_base_path = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(bp));
|
||||
}
|
||||
|
||||
SubDirectoryFileSystem::~SubDirectoryFileSystem() {
|
||||
if (m_base_path != nullptr) {
|
||||
fs::impl::Deallocate(m_base_path, m_base_path_len);
|
||||
}
|
||||
}
|
||||
|
||||
Result SubDirectoryFileSystem::Initialize(const char *bp) {
|
||||
/* Make sure the path isn't too long. */
|
||||
R_UNLESS(strnlen(bp, fs::EntryNameLengthMax + 1) <= fs::EntryNameLengthMax, fs::ResultTooLongPath());
|
||||
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 2];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, std::addressof(normalized_path_len), bp, sizeof(normalized_path), this->IsUncPreserved()));
|
||||
|
||||
/* Ensure terminating '/' */
|
||||
if (!fs::PathNormalizer::IsSeparator(normalized_path[normalized_path_len - 1])) {
|
||||
AMS_ASSERT(normalized_path_len + 2 < sizeof(normalized_path));
|
||||
normalized_path[normalized_path_len] = fs::StringTraits::DirectorySeparator;
|
||||
normalized_path[normalized_path_len + 1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
++normalized_path_len;
|
||||
}
|
||||
|
||||
/* Allocate new path. */
|
||||
m_base_path_len = normalized_path_len + 1;
|
||||
m_base_path = static_cast<char *>(fs::impl::Allocate(m_base_path_len));
|
||||
R_UNLESS(m_base_path != nullptr, fs::ResultAllocationFailureInSubDirectoryFileSystem());
|
||||
|
||||
/* Copy path in. */
|
||||
std::memcpy(m_base_path, normalized_path, normalized_path_len);
|
||||
m_base_path[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SubDirectoryFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
/* Ensure path will fit. */
|
||||
R_UNLESS(m_base_path_len + strnlen(relative_path, fs::EntryNameLengthMax + 1) <= out_size, fs::ResultTooLongPath());
|
||||
|
||||
/* Copy base path. */
|
||||
std::memcpy(out, m_base_path, m_base_path_len);
|
||||
|
||||
/* Normalize it. */
|
||||
const size_t prefix_size = m_base_path_len - 2;
|
||||
size_t normalized_len;
|
||||
return fs::PathNormalizer::Normalize(out + prefix_size, std::addressof(normalized_len), relative_path, out_size - prefix_size, this->IsUncPreserved(), false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,39 +19,43 @@ namespace ams::fssystem {
|
||||
|
||||
namespace {
|
||||
|
||||
inline Result EnsureDirectory(fs::fsa::IFileSystem *fs, const char *path) {
|
||||
R_TRY_CATCH(fs->CreateDirectory(path)) {
|
||||
R_CATCH(fs::ResultPathAlreadyExists) { /* If path already exists, there's no problem. */ }
|
||||
} R_END_TRY_CATCH;
|
||||
Result EnsureDirectoryImpl(fs::fsa::IFileSystem *fs, const fs::Path &path) {
|
||||
/* Create work path. */
|
||||
fs::Path work_path;
|
||||
R_TRY(work_path.Initialize(path));
|
||||
|
||||
return ResultSuccess();
|
||||
/* Create a directory path parser. */
|
||||
fs::DirectoryPathParser parser;
|
||||
R_TRY(parser.Initialize(std::addressof(work_path)));
|
||||
|
||||
bool is_finished;
|
||||
do {
|
||||
/* Get the current path. */
|
||||
const fs::Path &cur_path = parser.GetCurrentPath();
|
||||
|
||||
/* Get the entry type for the current path. */
|
||||
fs::DirectoryEntryType type;
|
||||
R_TRY_CATCH(fs->GetEntryType(std::addressof(type), cur_path)) {
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
/* The path doesn't exist. We should create it. */
|
||||
R_TRY(fs->CreateDirectory(cur_path));
|
||||
|
||||
/* Get the updated entry type. */
|
||||
R_TRY(fs->GetEntryType(std::addressof(type), cur_path));
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Verify that the current entry isn't a file. */
|
||||
R_UNLESS(type != fs::DirectoryEntryType_File, fs::ResultPathAlreadyExists());
|
||||
|
||||
/* Advance to the next part of the path. */
|
||||
R_TRY(parser.ReadNext(std::addressof(is_finished)));
|
||||
} while (!is_finished);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result EnsureDirectoryRecursivelyImpl(fs::fsa::IFileSystem *fs, const char *path, bool create_last) {
|
||||
/* Normalize the path. */
|
||||
char normalized_path[fs::EntryNameLengthMax + 1];
|
||||
size_t normalized_path_len;
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_path, std::addressof(normalized_path_len), path, sizeof(normalized_path)));
|
||||
|
||||
/* Repeatedly call CreateDirectory on each directory leading to the target. */
|
||||
for (size_t i = 1; i < normalized_path_len; i++) {
|
||||
/* If we detect a separator, create the directory. */
|
||||
if (fs::PathNormalizer::IsSeparator(normalized_path[i])) {
|
||||
normalized_path[i] = fs::StringTraits::NullTerminator;
|
||||
R_TRY(EnsureDirectory(fs, normalized_path));
|
||||
normalized_path[i] = fs::StringTraits::DirectorySeparator;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the last directory if requested. */
|
||||
if (create_last) {
|
||||
R_TRY(EnsureDirectory(fs, normalized_path));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result HasEntry(bool *out, fs::fsa::IFileSystem *fsa, const char *path, fs::DirectoryEntryType type) {
|
||||
Result HasEntry(bool *out, fs::fsa::IFileSystem *fsa, const fs::Path &path, fs::DirectoryEntryType type) {
|
||||
/* Set out to false initially. */
|
||||
*out = false;
|
||||
|
||||
@@ -64,30 +68,27 @@ namespace ams::fssystem {
|
||||
|
||||
/* We succeeded. */
|
||||
*out = entry_type == type;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result CopyFile(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const char *dst_parent_path, const char *src_path, const fs::DirectoryEntry *entry, void *work_buf, size_t work_buf_size) {
|
||||
Result CopyFile(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const fs::Path &dst_path, const fs::Path &src_path, void *work_buf, size_t work_buf_size) {
|
||||
/* Open source file. */
|
||||
std::unique_ptr<fs::fsa::IFile> src_file;
|
||||
R_TRY(src_fs->OpenFile(std::addressof(src_file), src_path, fs::OpenMode_Read));
|
||||
|
||||
/* Get the file size. */
|
||||
s64 file_size;
|
||||
R_TRY(src_file->GetSize(std::addressof(file_size)));
|
||||
|
||||
/* Open dst file. */
|
||||
std::unique_ptr<fs::fsa::IFile> dst_file;
|
||||
{
|
||||
char dst_path[fs::EntryNameLengthMax + 1];
|
||||
const size_t original_size = static_cast<size_t>(util::SNPrintf(dst_path, sizeof(dst_path), "%s%s", dst_parent_path, entry->name));
|
||||
/* TODO: Error code? N aborts here. */
|
||||
AMS_ABORT_UNLESS(original_size < sizeof(dst_path));
|
||||
|
||||
R_TRY(dst_fs->CreateFile(dst_path, entry->file_size));
|
||||
R_TRY(dst_fs->OpenFile(std::addressof(dst_file), dst_path, fs::OpenMode_Write));
|
||||
}
|
||||
R_TRY(dst_fs->CreateFile(dst_path, file_size));
|
||||
R_TRY(dst_fs->OpenFile(std::addressof(dst_file), dst_path, fs::OpenMode_Write));
|
||||
|
||||
/* Read/Write file in work buffer sized chunks. */
|
||||
s64 remaining = entry->file_size;
|
||||
s64 remaining = file_size;
|
||||
s64 offset = 0;
|
||||
while (remaining > 0) {
|
||||
size_t read_size;
|
||||
@@ -98,59 +99,63 @@ namespace ams::fssystem {
|
||||
offset += read_size;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CopyDirectoryRecursively(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const char *dst_path, const char *src_path, void *work_buf, size_t work_buf_size) {
|
||||
char dst_path_buf[fs::EntryNameLengthMax + 1];
|
||||
const size_t original_size = static_cast<size_t>(util::SNPrintf(dst_path_buf, sizeof(dst_path_buf), "%s", dst_path));
|
||||
AMS_ABORT_UNLESS(original_size < sizeof(dst_path_buf));
|
||||
Result CopyDirectoryRecursively(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const fs::Path &dst_path, const fs::Path &src_path, fs::DirectoryEntry *entry, void *work_buf, size_t work_buf_size) {
|
||||
/* Set up the destination work path to point at the target directory. */
|
||||
fs::Path dst_work_path;
|
||||
R_TRY(dst_work_path.Initialize(dst_path));
|
||||
|
||||
return IterateDirectoryRecursively(src_fs, src_path,
|
||||
[&](const char *path, const fs::DirectoryEntry &entry) -> Result { /* On Enter Directory */
|
||||
AMS_UNUSED(path);
|
||||
|
||||
/* Update path, create new dir. */
|
||||
std::strncat(dst_path_buf, entry.name, sizeof(dst_path_buf) - strnlen(dst_path_buf, sizeof(dst_path_buf) - 1) - 1);
|
||||
std::strncat(dst_path_buf, "/", sizeof(dst_path_buf) - strnlen(dst_path_buf, sizeof(dst_path_buf) - 1) - 1);
|
||||
return dst_fs->CreateDirectory(dst_path_buf);
|
||||
},
|
||||
[&](const char *path, const fs::DirectoryEntry &entry) -> Result { /* On Exit Directory */
|
||||
/* Iterate, copying files. */
|
||||
R_RETURN(IterateDirectoryRecursively(src_fs, src_path, entry,
|
||||
[&](const fs::Path &path, const fs::DirectoryEntry &entry) -> Result { /* On Enter Directory */
|
||||
AMS_UNUSED(path, entry);
|
||||
|
||||
/* Check we have a parent directory. */
|
||||
const size_t len = strnlen(dst_path_buf, sizeof(dst_path_buf));
|
||||
R_UNLESS(len >= 2, fs::ResultInvalidPathFormat());
|
||||
/* Append the current entry to the dst work path. */
|
||||
R_TRY(dst_work_path.AppendChild(entry.name));
|
||||
|
||||
/* Find previous separator, add null terminator */
|
||||
char *cur = dst_path_buf + len - 2;
|
||||
while (!fs::PathNormalizer::IsSeparator(*cur) && cur > dst_path_buf) {
|
||||
cur--;
|
||||
}
|
||||
cur[1] = fs::StringTraits::NullTerminator;
|
||||
|
||||
return ResultSuccess();
|
||||
/* Create the directory. */
|
||||
R_RETURN(dst_fs->CreateDirectory(dst_work_path));
|
||||
},
|
||||
[&](const char *path, const fs::DirectoryEntry &entry) -> Result { /* On File */
|
||||
return CopyFile(dst_fs, src_fs, dst_path_buf, path, std::addressof(entry), work_buf, work_buf_size);
|
||||
[&](const fs::Path &path, const fs::DirectoryEntry &entry) -> Result { /* On Exit Directory */
|
||||
AMS_UNUSED(path, entry);
|
||||
|
||||
/* Remove the directory we're leaving from the dst work path. */
|
||||
R_RETURN(dst_work_path.RemoveChild());
|
||||
},
|
||||
[&](const fs::Path &path, const fs::DirectoryEntry &entry) -> Result { /* On File */
|
||||
/* Append the current entry to the dst work path. */
|
||||
R_TRY(dst_work_path.AppendChild(entry.name));
|
||||
|
||||
/* Copy the file. */
|
||||
R_TRY(fssystem::CopyFile(dst_fs, src_fs, dst_work_path, path, work_buf, work_buf_size));
|
||||
|
||||
/* Remove the current entry from the dst work path. */
|
||||
R_RETURN(dst_work_path.RemoveChild());
|
||||
}
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
Result HasFile(bool *out, fs::fsa::IFileSystem *fs, const char *path) {
|
||||
return HasEntry(out, fs, path, fs::DirectoryEntryType_File);
|
||||
Result HasFile(bool *out, fs::fsa::IFileSystem *fs, const fs::Path &path) {
|
||||
R_RETURN(HasEntry(out, fs, path, fs::DirectoryEntryType_File));
|
||||
}
|
||||
|
||||
Result HasDirectory(bool *out, fs::fsa::IFileSystem *fs, const char *path) {
|
||||
return HasEntry(out, fs, path, fs::DirectoryEntryType_Directory);
|
||||
Result HasDirectory(bool *out, fs::fsa::IFileSystem *fs, const fs::Path &path) {
|
||||
R_RETURN(HasEntry(out, fs, path, fs::DirectoryEntryType_Directory));
|
||||
}
|
||||
|
||||
Result EnsureDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *path) {
|
||||
return EnsureDirectoryRecursivelyImpl(fs, path, true);
|
||||
}
|
||||
Result EnsureDirectory(fs::fsa::IFileSystem *fs, const fs::Path &path) {
|
||||
/* First, check if the directory already exists. If it does, we're good to go. */
|
||||
fs::DirectoryEntryType type;
|
||||
R_TRY_CATCH(fs->GetEntryType(std::addressof(type), path)) {
|
||||
/* If the directory doesn't already exist, we should create it. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(EnsureDirectoryImpl(fs, path));
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
Result EnsureParentDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *path) {
|
||||
return EnsureDirectoryRecursivelyImpl(fs, path, false);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void AddCounter(void *_counter, size_t counter_size, u64 value) {
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace ams::fssystem::save {
|
||||
/* Initialize the top level verification storage. */
|
||||
{
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[0].key, KeyArray[0].size);
|
||||
crypto::GenerateHmacSha256(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[0].key, KeyArray[0].size);
|
||||
m_verify_storages[0].Initialize(storage[HierarchicalStorageInformation::MasterStorage], storage[HierarchicalStorageInformation::Layer1Storage], static_cast<s64>(1) << info.info[0].block_order, HashSize, m_buffers->buffers[m_max_layers - 2], hgf, mac, false, storage_type);
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace ams::fssystem::save {
|
||||
{
|
||||
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
crypto::GenerateHmacSha256(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], hgf, mac, false, storage_type);
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace ams::fssystem::save {
|
||||
{
|
||||
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
crypto::GenerateHmacSha256(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], hgf, mac, true, storage_type);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user