fs/system: deduplicate RomFs code

This commit is contained in:
Michael Scire 2020-12-04 22:08:33 -08:00
parent c45088d1cd
commit 73167448cc
16 changed files with 226 additions and 1723 deletions

View file

@ -1,189 +0,0 @@
/*
* Copyright (c) 2018-2020 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::RomPathTool {
Result PathParser::Initialize(const RomPathChar *path) {
AMS_ASSERT(path != nullptr);
/* Require paths start with a separator, and skip repeated separators. */
R_UNLESS(IsSeparator(path[0]), fs::ResultDbmInvalidPathFormat());
while (IsSeparator(path[1])) {
path++;
}
this->prev_path_start = path;
this->prev_path_end = path;
this->next_path = path + 1;
while (IsSeparator(this->next_path[0])) {
this->next_path++;
}
return ResultSuccess();
}
void PathParser::Finalize() {
/* ... */
}
bool PathParser::IsFinished() const {
return this->finished;
}
bool PathParser::IsDirectoryPath() const {
AMS_ASSERT(this->next_path != nullptr);
if (IsNullTerminator(this->next_path[0]) && IsSeparator(this->next_path[-1])) {
return true;
}
if (IsCurrentDirectory(this->next_path)) {
return true;
}
if (IsParentDirectory(this->next_path)) {
return true;
}
return false;
}
Result PathParser::GetAsDirectoryName(RomEntryName *out) const {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(this->prev_path_start != nullptr);
AMS_ASSERT(this->prev_path_end != nullptr);
AMS_ASSERT(this->next_path != nullptr);
const size_t len = this->prev_path_end - this->prev_path_start;
R_UNLESS(len <= MaxPathLength, fs::ResultDbmDirectoryNameTooLong());
out->length = len;
out->path = this->prev_path_start;
return ResultSuccess();
}
Result PathParser::GetAsFileName(RomEntryName *out) const {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(this->prev_path_start != nullptr);
AMS_ASSERT(this->prev_path_end != nullptr);
AMS_ASSERT(this->next_path != nullptr);
const size_t len = this->prev_path_end - this->prev_path_start;
R_UNLESS(len <= MaxPathLength, fs::ResultDbmFileNameTooLong());
out->length = len;
out->path = this->prev_path_start;
return ResultSuccess();
}
Result PathParser::GetNextDirectoryName(RomEntryName *out) {
AMS_ASSERT(out != nullptr);
AMS_ASSERT(this->prev_path_start != nullptr);
AMS_ASSERT(this->prev_path_end != nullptr);
AMS_ASSERT(this->next_path != nullptr);
/* Set the current path to output. */
out->length = this->prev_path_end - this->prev_path_start;
out->path = this->prev_path_start;
/* Parse the next path. */
this->prev_path_start = this->next_path;
const RomPathChar *cur = this->next_path;
for (size_t name_len = 0; true; name_len++) {
if (IsSeparator(cur[name_len])) {
R_UNLESS(name_len < MaxPathLength, fs::ResultDbmDirectoryNameTooLong());
this->prev_path_end = cur + name_len;
this->next_path = this->prev_path_end + 1;
while (IsSeparator(this->next_path[0])) {
this->next_path++;
}
if (IsNullTerminator(this->next_path[0])) {
this->finished = true;
}
break;
}
if (IsNullTerminator(cur[name_len])) {
this->finished = true;
this->prev_path_end = this->next_path = cur + name_len;
break;
}
}
return ResultSuccess();
}
Result GetParentDirectoryName(RomEntryName *out, const RomEntryName &cur, const RomPathChar *p) {
const RomPathChar *start = cur.path;
const RomPathChar *end = cur.path + cur.length - 1;
s32 depth = 1;
if (IsParentDirectory(cur)) {
depth++;
}
if (cur.path > p) {
size_t len = 0;
const RomPathChar *head = cur.path - 1;
while (head >= p) {
if (IsSeparator(*head)) {
if (IsCurrentDirectory(head + 1, len)) {
depth++;
}
if (IsParentDirectory(head + 1, len)) {
depth += 2;
}
if (depth == 0) {
start = head + 1;
break;
}
while (IsSeparator(*head)) {
head--;
}
end = head;
len = 0;
depth--;
}
len++;
head--;
}
R_UNLESS(depth == 0, fs::ResultDbmInvalidPathFormat());
if (head == p) {
start = p + 1;
}
}
if (end <= p) {
out->path = p;
out->length = 0;
} else {
out->path = start;
out->length = end - start + 1;
}
return ResultSuccess();
}
}

View file

@ -19,7 +19,7 @@ namespace ams::fssystem {
namespace {
constexpr size_t CalculateRequiredWorkingMemorySize(const RomFileSystemInformation &header) {
constexpr size_t CalculateRequiredWorkingMemorySize(const fs::RomFileSystemInformation &header) {
return header.directory_bucket_size + header.directory_entry_size + header.file_bucket_size + header.file_entry_size;
}
@ -114,7 +114,7 @@ namespace ams::fssystem {
public:
virtual Result ReadImpl(s64 *out_count, fs::DirectoryEntry *out_entries, s64 max_entries) {
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
return this->ReadImpl(out_count, std::addressof(this->current_find), out_entries, max_entries);
return this->ReadInternal(out_count, std::addressof(this->current_find), out_entries, max_entries);
}, AMS_CURRENT_FUNCTION_NAME));
return ResultSuccess();
}
@ -123,20 +123,20 @@ namespace ams::fssystem {
FindPosition find = this->first_find;
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
R_TRY(this->ReadImpl(out, std::addressof(find), nullptr, 0));
R_TRY(this->ReadInternal(out, std::addressof(find), nullptr, 0));
return ResultSuccess();
}, AMS_CURRENT_FUNCTION_NAME));
return ResultSuccess();
}
private:
Result ReadImpl(s64 *out_count, FindPosition *find, fs::DirectoryEntry *out_entries, s64 max_entries) {
Result ReadInternal(s64 *out_count, FindPosition *find, fs::DirectoryEntry *out_entries, s64 max_entries) {
constexpr size_t NameBufferSize = fs::EntryNameLengthMax + 1;
RomPathChar name[NameBufferSize];
fs::RomPathChar name[NameBufferSize];
s32 i = 0;
if (this->mode & fs::OpenDirectoryMode_Directory) {
while (i < max_entries || out_entries == nullptr) {
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextDirectory(name, find)) {
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextDirectory(name, find, NameBufferSize)) {
R_CATCH(fs::ResultDbmFindFinished) { break; }
} R_END_TRY_CATCH;
@ -156,7 +156,7 @@ namespace ams::fssystem {
while (i < max_entries || out_entries == nullptr) {
auto file_pos = find->next_file;
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextFile(name, find)) {
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextFile(name, find, NameBufferSize)) {
R_CATCH(fs::ResultDbmFindFinished) { break; }
} R_END_TRY_CATCH;
@ -167,7 +167,7 @@ namespace ams::fssystem {
out_entries[i].type = fs::DirectoryEntryType_File;
RomFsFileSystem::RomFileTable::FileInfo file_info;
R_TRY(this->parent->GetRomFileTable()->OpenFile(std::addressof(file_info), this->parent->GetRomFileTable()->ConvertToFileId(file_pos)));
R_TRY(this->parent->GetRomFileTable()->OpenFile(std::addressof(file_info), this->parent->GetRomFileTable()->PositionToFileId(file_pos)));
out_entries[i].file_size = file_info.size.Get();
}
@ -204,7 +204,7 @@ namespace ams::fssystem {
}
Result RomFsFileSystem::GetRequiredWorkingMemorySize(size_t *out, fs::IStorage *storage) {
RomFileSystemInformation header;
fs::RomFileSystemInformation header;
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
R_TRY(storage->Read(0, std::addressof(header), sizeof(header)));
@ -224,7 +224,7 @@ namespace ams::fssystem {
buffers::EnableBlockingBufferManagerAllocation();
/* Read the header. */
RomFileSystemInformation header;
fs::RomFileSystemInformation header;
R_TRY(base->Read(0, std::addressof(header), sizeof(header)));
/* Set up our storages. */
@ -261,10 +261,10 @@ namespace ams::fssystem {
R_UNLESS(this->file_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
/* Initialize the rom table. */
R_TRY(this->rom_file_table.Initialize(this->dir_bucket_storage.get(), 0, static_cast<u32>(header.directory_bucket_size),
this->dir_entry_storage.get(), 0, static_cast<u32>(header.directory_entry_size),
this->file_bucket_storage.get(), 0, static_cast<u32>(header.file_bucket_size),
this->file_entry_storage.get(), 0, static_cast<u32>(header.file_entry_size)));
R_TRY(this->rom_file_table.Initialize(fs::SubStorage(this->dir_bucket_storage.get(), 0, static_cast<u32>(header.directory_bucket_size)),
fs::SubStorage(this->dir_entry_storage.get(), 0, static_cast<u32>(header.directory_entry_size)),
fs::SubStorage(this->file_bucket_storage.get(), 0, static_cast<u32>(header.file_bucket_size)),
fs::SubStorage(this->file_entry_storage.get(), 0, static_cast<u32>(header.file_entry_size))));
/* Set members. */
this->entry_size = header.body_offset;
@ -326,7 +326,7 @@ namespace ams::fssystem {
Result RomFsFileSystem::GetEntryTypeImpl(fs::DirectoryEntryType *out, const char *path) {
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
RomDirectoryInfo dir_info;
fs::RomDirectoryInfo dir_info;
R_TRY_CATCH(this->rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())