From 4e29d98e22ed1551f4e69f9074d1ce2e2adea5fd Mon Sep 17 00:00:00 2001 From: Adubbz Date: Wed, 4 Mar 2020 15:21:20 +1100 Subject: [PATCH] ncm: Use PathString and Path --- .../include/stratosphere/ncm/ncm_path.hpp | 3 + .../include/stratosphere/ncm/ncm_types.hpp | 3 - .../source/impl/ncm_placeholder_accessor.cpp | 35 ++--- .../source/impl/ncm_placeholder_accessor.hpp | 18 +-- .../ncm/source/ncm_content_storage_impl.cpp | 141 +++++++++--------- .../ncm/source/ncm_content_storage_impl.hpp | 13 +- .../source/ncm_content_storage_impl_base.hpp | 8 +- stratosphere/ncm/source/ncm_fs.cpp | 23 +-- stratosphere/ncm/source/ncm_make_path.cpp | 51 ++++--- stratosphere/ncm/source/ncm_make_path.hpp | 12 +- stratosphere/ncm/source/ncm_path_utils.cpp | 20 +-- stratosphere/ncm/source/ncm_path_utils.hpp | 12 +- .../ncm_read_only_content_storage_impl.cpp | 54 ++++--- 13 files changed, 195 insertions(+), 198 deletions(-) diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_path.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_path.hpp index 79799c674..a47080245 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_path.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_path.hpp @@ -39,4 +39,7 @@ namespace ams::ncm { using PathString = kvdb::BoundedString; + using MakeContentPathFunc = void (*)(PathString *out, ContentId content_id, const PathString &root); + using MakePlaceHolderPathFunc = void (*)(PathString *out, PlaceHolderId placeholder_id, const PathString &root); + } diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp index 7927e8561..31fdd73e6 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_types.hpp @@ -145,9 +145,6 @@ namespace ams::ncm { static_assert(sizeof(std::is_pod::value)); static_assert(sizeof(ContentInfo) == 0x18); - using MakeContentPathFunc = void (*)(char *out, ContentId content_id, const char *root); - using MakePlaceHolderPathFunc = void (*)(char *out, PlaceHolderId placeholder_id, const char *root); - /* Storage IDs. */ enum class StorageId : u8 { #define DEFINE_ENUM_MEMBER(nm) nm = NcmStorageId_##nm diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 87649c95c..5be23b3ef 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -35,8 +35,8 @@ namespace ams::ncm::impl { Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { R_UNLESS(!this->LoadFromCache(out_handle, placeholder_id), ResultSuccess()); - char placeholder_path[FS_MAX_PATH] = {0}; - this->MakePath(placeholder_path, placeholder_id); + PathString placeholder_path; + this->MakePath(std::addressof(placeholder_path), placeholder_id); FILE *f = nullptr; R_TRY(fs::OpenFile(&f, placeholder_path, FsOpenMode_Write)); @@ -102,8 +102,8 @@ namespace ams::ncm::impl { } } - void PlaceHolderAccessor::Initialize(char *root, MakePlaceHolderPathFunc path_func, bool delay_flush) { - this->root_path = root; + void PlaceHolderAccessor::Initialize(const char *root, MakePlaceHolderPathFunc path_func, bool delay_flush) { + this->root_path = PathString(root); this->make_placeholder_path_func = path_func; this->delay_flush = delay_flush; } @@ -116,20 +116,22 @@ namespace ams::ncm::impl { } else { AMS_ABORT(); } + + __builtin_unreachable(); } - void PlaceHolderAccessor::GetPath(char *placeholder_path_out, PlaceHolderId placeholder_id) { + void PlaceHolderAccessor::GetPath(PathString *placeholder_path, PlaceHolderId placeholder_id) { std::scoped_lock lock(this->cache_mutex); CacheEntry *entry = this->FindInCache(placeholder_id); this->Invalidate(entry); - this->MakePath(placeholder_path_out, placeholder_id); + this->MakePath(placeholder_path, placeholder_id); } Result PlaceHolderAccessor::Create(PlaceHolderId placeholder_id, size_t size) { - char placeholder_path[FS_MAX_PATH] = {0}; - this->EnsureRecursively(placeholder_id); - this->GetPath(placeholder_path, placeholder_id); + + PathString placeholder_path; + this->GetPath(std::addressof(placeholder_path), placeholder_id); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FsCreateOption_BigFile)) { R_CONVERT(ams::fs::ResultPathAlreadyExists, ncm::ResultPlaceHolderAlreadyExists()) @@ -139,11 +141,10 @@ namespace ams::ncm::impl { } Result PlaceHolderAccessor::Delete(PlaceHolderId placeholder_id) { - char placeholder_path[FS_MAX_PATH] = {0}; + PathString placeholder_path; + this->GetPath(std::addressof(placeholder_path), placeholder_id); - this->GetPath(placeholder_path, placeholder_id); R_UNLESS(std::remove(placeholder_path) == 0, ConvertNotFoundResult(fsdevGetLastResult())); - return ResultSuccess(); } @@ -158,10 +159,10 @@ namespace ams::ncm::impl { } Result PlaceHolderAccessor::SetSize(PlaceHolderId placeholder_id, size_t size) { - char placeholder_path[FS_MAX_PATH] = {0}; - this->MakePath(placeholder_path, placeholder_id); - R_UNLESS(truncate(placeholder_path, size) != -1, ConvertNotFoundResult(fsdevGetLastResult())); + PathString placeholder_path; + this->MakePath(std::addressof(placeholder_path), placeholder_id); + R_UNLESS(truncate(placeholder_path, size) != -1, ConvertNotFoundResult(fsdevGetLastResult())); return ResultSuccess(); } @@ -198,8 +199,8 @@ namespace ams::ncm::impl { } Result PlaceHolderAccessor::EnsureRecursively(PlaceHolderId placeholder_id) { - char placeholder_path[FS_MAX_PATH] = {0}; - this->MakePath(placeholder_path, placeholder_id); + PathString placeholder_path; + this->MakePath(std::addressof(placeholder_path), placeholder_id); R_TRY(fs::EnsureParentDirectoryRecursively(placeholder_path)); return ResultSuccess(); } diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index 0f5c5ecdb..3a656cc87 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -34,7 +34,7 @@ namespace ams::ncm::impl { static constexpr size_t MaxCaches = 0x2; std::array caches; - char *root_path; + PathString root_path; u64 cur_counter; os::Mutex cache_mutex; MakePlaceHolderPathFunc make_placeholder_path_func; @@ -53,19 +53,19 @@ namespace ams::ncm::impl { } } - inline void MakeRootPath(char *out_placeholder_root) { - path::GetPlaceHolderRootPath(out_placeholder_root, this->root_path); + inline void MakeRootPath(PathString *placeholder_root) { + path::GetPlaceHolderRootPath(placeholder_root, this->root_path); } - inline void MakePath(char *out_placeholder_path, PlaceHolderId placeholder_id) { - char placeholder_root_path[FS_MAX_PATH] = {0}; - this->MakeRootPath(placeholder_root_path); - this->make_placeholder_path_func(out_placeholder_path, placeholder_id, placeholder_root_path); + inline void MakePath(PathString *placeholder_path, PlaceHolderId placeholder_id) { + PathString root_path; + this->MakeRootPath(std::addressof(root_path)); + this->make_placeholder_path_func(placeholder_path, placeholder_id, root_path); } - void Initialize(char *root, MakePlaceHolderPathFunc path_func, bool delay_flush); + void Initialize(const char *root, MakePlaceHolderPathFunc path_func, bool delay_flush); unsigned int GetDirectoryDepth(); - void GetPath(char *out_placeholder_path, PlaceHolderId placeholder_id); + void GetPath(PathString *out_placeholder_path, PlaceHolderId placeholder_id); Result Create(PlaceHolderId placeholder_id, size_t size); Result Delete(PlaceHolderId placeholder_id); Result Write(PlaceHolderId placeholder_id, size_t offset, const void *buffer, size_t size); diff --git a/stratosphere/ncm/source/ncm_content_storage_impl.cpp b/stratosphere/ncm/source/ncm_content_storage_impl.cpp index fe586f1bc..c474e2528 100644 --- a/stratosphere/ncm/source/ncm_content_storage_impl.cpp +++ b/stratosphere/ncm/source/ncm_content_storage_impl.cpp @@ -25,14 +25,11 @@ namespace ams::ncm { this->Finalize(); } - Result ContentStorageImpl::Initialize(const char *root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache *rights_id_cache) { + Result ContentStorageImpl::Initialize(const char *path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache *rights_id_cache) { R_TRY(this->EnsureEnabled()); - R_TRY(fs::CheckContentStorageDirectoriesExist(root_path)); - const size_t root_path_len = strnlen(root_path, ams::fs::EntryNameLengthMax); + R_TRY(fs::CheckContentStorageDirectoriesExist(path)); - AMS_ABORT_UNLESS(root_path_len < ams::fs::EntryNameLengthMax); - - strncpy(this->root_path, root_path, FS_MAX_PATH-2); + this->root_path = PathString(path); this->make_content_path_func = *content_path_func; this->placeholder_accessor.Initialize(this->root_path, *placeholder_path_func, delay_flush); this->rights_id_cache = rights_id_cache; @@ -69,8 +66,9 @@ namespace ams::ncm { R_UNLESS(this->cached_content_id != content_id, ResultSuccess()); this->ClearContentCache(); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); R_TRY_CATCH(fs::OpenFile(&this->content_cache_file_handle, content_path, FsOpenMode_Read)) { R_CONVERT(ams::fs::ResultPathNotFound, ncm::ResultContentNotFound()) @@ -89,8 +87,8 @@ namespace ams::ncm { Result ContentStorageImpl::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); R_TRY(fs::EnsureParentDirectoryRecursively(content_path)); R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); @@ -106,8 +104,8 @@ namespace ams::ncm { Result ContentStorageImpl::HasPlaceHolder(sf::Out out, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); - char placeholder_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.MakePath(placeholder_path, placeholder_id); + PathString placeholder_path; + this->placeholder_accessor.MakePath(std::addressof(placeholder_path), placeholder_id); bool has = false; R_TRY(fs::HasFile(&has, placeholder_path)); @@ -128,11 +126,10 @@ namespace ams::ncm { this->ClearContentCache(); R_TRY(this->EnsureEnabled()); - char placeholder_path[FS_MAX_PATH] = {0}; - char content_path[FS_MAX_PATH] = {0}; - - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - this->GetContentPath(content_path, content_id); + PathString placeholder_path; + PathString content_path; + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); + this->GetContentPath(std::addressof(content_path), content_id); if (rename(placeholder_path, content_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { @@ -148,8 +145,9 @@ namespace ams::ncm { R_TRY(this->EnsureEnabled()); this->ClearContentCache(); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); if (std::remove(content_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { @@ -163,8 +161,8 @@ namespace ams::ncm { Result ContentStorageImpl::Has(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); bool has = false; R_TRY(fs::HasFile(&has, content_path)); @@ -176,31 +174,33 @@ namespace ams::ncm { Result ContentStorageImpl::GetPath(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, content_path)); - out.SetValue(Path::Encode(common_path)); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); + + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, content_path)); + out.SetValue(Path::Encode(common_path.str)); return ResultSuccess(); } Result ContentStorageImpl::GetPlaceHolderPath(sf::Out out, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); - char placeholder_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, placeholder_path)); - out.SetValue(Path::Encode(common_path)); + PathString placeholder_path; + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); + + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, placeholder_path)); + out.SetValue(Path::Encode(common_path.str)); return ResultSuccess(); } Result ContentStorageImpl::CleanupAllPlaceHolder() { R_TRY(this->EnsureEnabled()); - char placeholder_root_path[FS_MAX_PATH] = {0}; + PathString placeholder_root_path; this->placeholder_accessor.InvalidateAll(); - this->placeholder_accessor.MakeRootPath(placeholder_root_path); + this->placeholder_accessor.MakeRootPath(std::addressof(placeholder_root_path)); /* Nintendo uses CleanDirectoryRecursively which is 3.0.0+. We'll just delete the directory and recreate it to support all firmwares. */ @@ -212,8 +212,8 @@ namespace ams::ncm { Result ContentStorageImpl::ListPlaceHolder(sf::Out out_count, const sf::OutArray &out_buf) { R_TRY(this->EnsureEnabled()); - char placeholder_root_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.MakeRootPath(placeholder_root_path); + PathString placeholder_root_path; + this->placeholder_accessor.MakeRootPath(std::addressof(placeholder_root_path)); const unsigned int dir_depth = this->placeholder_accessor.GetDirectoryDepth(); size_t entry_count = 0; @@ -239,8 +239,8 @@ namespace ams::ncm { Result ContentStorageImpl::GetContentCount(sf::Out out_count) { R_TRY(this->EnsureEnabled()); - char content_root_path[FS_MAX_PATH] = {0}; - this->GetContentRootPath(content_root_path); + PathString content_root_path; + this->GetContentRootPath(std::addressof(content_root_path)); const unsigned int dir_depth = this->GetContentDirectoryDepth(); u32 content_count = 0; @@ -263,8 +263,9 @@ namespace ams::ncm { R_UNLESS(start_offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); - char content_root_path[FS_MAX_PATH] = {0}; - this->GetContentRootPath(content_root_path); + PathString content_root_path; + this->GetContentRootPath(std::addressof(content_root_path)); + const unsigned int dir_depth = this->GetContentDirectoryDepth(); size_t entry_count = 0; @@ -311,8 +312,8 @@ namespace ams::ncm { Result ContentStorageImpl::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); struct stat st; R_UNLESS(stat(content_path, &st) != -1, fsdevGetLastResult()); @@ -330,18 +331,18 @@ namespace ams::ncm { Result ContentStorageImpl::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { R_TRY(this->EnsureEnabled()); - char old_content_path[FS_MAX_PATH] = {0}; - char new_content_path[FS_MAX_PATH] = {0}; - char placeholder_path[FS_MAX_PATH] = {0}; + PathString old_content_path; + PathString new_content_path; + PathString placeholder_path; this->ClearContentCache(); /* Ensure the new content path is ready. */ - this->GetContentPath(new_content_path, new_content_id); + this->GetContentPath(std::addressof(new_content_path), new_content_id); R_TRY(fs::EnsureParentDirectoryRecursively(new_content_path)); R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); if (rename(old_content_path, placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CONVERT(ams::fs::ResultPathNotFound, ncm::ResultPlaceHolderNotFound()) @@ -362,8 +363,10 @@ namespace ams::ncm { /* Offset is too large */ R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); + R_TRY(this->OpenCachedContentFile(content_id)); R_TRY(fs::ReadFile(this->content_cache_file_handle, offset, buf.GetPointer(), buf.GetSize())); @@ -380,10 +383,11 @@ namespace ams::ncm { Result ContentStorageImpl::GetRightsIdFromPlaceHolderId(sf::Out out_rights_id, PlaceHolderId placeholder_id) { R_TRY(this->EnsureEnabled()); - char placeholder_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, placeholder_path)); + PathString placeholder_path; + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); + + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, placeholder_path)); ncm::RightsId rights_id; R_TRY(GetRightsId(&rights_id, common_path)); @@ -406,10 +410,11 @@ namespace ams::ncm { return ResultSuccess(); } - char content_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, content_path)); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); + + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, content_path)); ncm::RightsId rights_id; R_TRY(GetRightsId(&rights_id, common_path)); @@ -432,8 +437,8 @@ namespace ams::ncm { this->ClearContentCache(); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); + PathString content_path; + this->GetContentPath(std::addressof(content_path), content_id); FILE *f = nullptr; R_TRY(fs::OpenFile(&f, content_path, FsOpenMode_Write)); @@ -479,10 +484,10 @@ namespace ams::ncm { return ResultSuccess(); } - char placeholder_path[FS_MAX_PATH] = {0}; + PathString placeholder_path; struct stat st; - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); R_UNLESS(stat(placeholder_path, &st) != -1, fsdevGetLastResult()); out_size.SetValue(st.st_size); @@ -490,8 +495,8 @@ namespace ams::ncm { } Result ContentStorageImpl::RepairInvalidFileAttribute() { - char content_root_path[FS_MAX_PATH] = {0}; - this->GetContentRootPath(content_root_path); + PathString content_root_path; + this->GetContentRootPath(std::addressof(content_root_path)); unsigned int dir_depth = this->GetContentDirectoryDepth(); auto fix_file_attributes = [&](bool *should_continue, bool *should_retry_dir_read, const char *current_path, struct dirent *dir_entry) { *should_retry_dir_read = false; @@ -510,9 +515,9 @@ namespace ams::ncm { R_TRY(fs::TraverseDirectory(content_root_path, dir_depth, fix_file_attributes)); - char placeholder_root_path[FS_MAX_PATH] = {0}; + PathString placeholder_root_path; this->placeholder_accessor.InvalidateAll(); - this->placeholder_accessor.MakeRootPath(placeholder_root_path); + this->placeholder_accessor.MakeRootPath(std::addressof(placeholder_root_path)); dir_depth = this->placeholder_accessor.GetDirectoryDepth(); R_TRY(fs::TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); @@ -527,11 +532,11 @@ namespace ams::ncm { return ResultSuccess(); } - char common_path[FS_MAX_PATH] = {0}; - char placeholder_path[FS_MAX_PATH] = {0}; + PathString placeholder_path; + this->placeholder_accessor.GetPath(std::addressof(placeholder_path), placeholder_id); - this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, placeholder_path)); + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, placeholder_path)); ncm::RightsId rights_id; R_TRY(GetRightsId(&rights_id, common_path)); diff --git a/stratosphere/ncm/source/ncm_content_storage_impl.hpp b/stratosphere/ncm/source/ncm_content_storage_impl.hpp index c273fdf7a..c7c3afbb6 100644 --- a/stratosphere/ncm/source/ncm_content_storage_impl.hpp +++ b/stratosphere/ncm/source/ncm_content_storage_impl.hpp @@ -41,15 +41,14 @@ namespace ams::ncm { unsigned int GetContentDirectoryDepth(); Result OpenCachedContentFile(ContentId content_id); - inline void GetContentRootPath(char *out_content_root) { - path::GetContentRootPath(out_content_root, this->root_path); + inline void GetContentRootPath(PathString *content_root) { + path::GetContentRootPath(content_root, this->root_path); } - inline void GetContentPath(char *out_content_path, ContentId content_id) { - char content_root_path[FS_MAX_PATH] = {0}; - - this->GetContentRootPath(content_root_path); - this->make_content_path_func(out_content_path, content_id, content_root_path); + inline void GetContentPath(PathString *content_path, ContentId content_id) { + PathString root_path; + this->GetContentRootPath(std::addressof(root_path)); + this->make_content_path_func(content_path, content_id, root_path); } public: virtual Result GeneratePlaceHolderId(sf::Out out) override; diff --git a/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp b/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp index 3f32a6b42..03f59caef 100644 --- a/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp +++ b/stratosphere/ncm/source/ncm_content_storage_impl_base.hpp @@ -23,7 +23,7 @@ namespace ams::ncm { NON_COPYABLE(ContentStorageImplBase); NON_MOVEABLE(ContentStorageImplBase); protected: - char root_path[ams::fs::EntryNameLengthMax]; + PathString root_path; MakeContentPathFunc make_content_path_func; bool disabled; protected: @@ -34,11 +34,11 @@ namespace ams::ncm { return ResultSuccess(); } - static Result GetRightsId(ncm::RightsId *out_rights_id, const char *path) { + static Result GetRightsId(ncm::RightsId *out_rights_id, const Path &path) { if (hos::GetVersion() >= hos::Version_300) { - R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), std::addressof(out_rights_id->key_generation), path)); + R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), std::addressof(out_rights_id->key_generation), path.str)); } else { - R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), path)); + R_TRY(ams::fs::GetRightsId(std::addressof(out_rights_id->id), path.str)); out_rights_id->key_generation = 0; } return ResultSuccess(); diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index d001e375e..def06f20e 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -98,20 +98,21 @@ namespace ams::ncm::fs { return ResultSuccess(); } - Result CheckContentStorageDirectoriesExist(const char *root_path) { - char content_root[FS_MAX_PATH] = {0}; - char placeholder_root[FS_MAX_PATH] = {0}; + Result CheckContentStorageDirectoriesExist(const char *path) { + const PathString root_path(path); bool has_root = false; R_TRY(HasDirectory(&has_root, root_path)); R_UNLESS(has_root, ncm::ResultContentStorageBaseNotFound()); - path::GetContentRootPath(content_root, root_path); + PathString content_root; + path::GetContentRootPath(std::addressof(content_root), root_path); bool has_content_root = false; R_TRY(HasDirectory(&has_content_root, content_root)); R_UNLESS(has_content_root, ncm::ResultInvalidContentStorageBase()); - path::GetPlaceHolderRootPath(placeholder_root, root_path); + PathString placeholder_root; + path::GetPlaceHolderRootPath(std::addressof(placeholder_root), root_path); bool has_placeholder_root = false; R_TRY(HasDirectory(&has_placeholder_root, placeholder_root)); R_UNLESS(has_placeholder_root, ncm::ResultInvalidContentStorageBase()); @@ -119,13 +120,15 @@ namespace ams::ncm::fs { return ResultSuccess(); } - Result EnsureContentAndPlaceHolderRoot(const char *root_path) { - char content_root[FS_MAX_PATH] = {0}; - char placeholder_root[FS_MAX_PATH] = {0}; + Result EnsureContentAndPlaceHolderRoot(const char *path) { + const PathString root_path(path); - path::GetContentRootPath(content_root, root_path); + PathString content_root; + path::GetContentRootPath(std::addressof(content_root), root_path); R_TRY(EnsureDirectoryRecursively(content_root)); - path::GetPlaceHolderRootPath(placeholder_root, root_path); + + PathString placeholder_root; + path::GetPlaceHolderRootPath(std::addressof(placeholder_root), root_path); R_TRY(EnsureDirectoryRecursively(placeholder_root)); return ResultSuccess(); diff --git a/stratosphere/ncm/source/ncm_make_path.cpp b/stratosphere/ncm/source/ncm_make_path.cpp index fa940edaf..1f2f6e7cb 100644 --- a/stratosphere/ncm/source/ncm_make_path.cpp +++ b/stratosphere/ncm/source/ncm_make_path.cpp @@ -35,47 +35,50 @@ namespace ams::ncm::path { } - void MakeContentPathFlat(char *path_out, ContentId content_id, const char *root) { - char content_name[FS_MAX_PATH] = {0}; - GetContentFileName(content_name, content_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%s", root, content_name) >= 0); + void MakeContentPathFlat(PathString *out, ContentId content_id, const PathString &root) { + Path content_name; + GetContentFileName(content_name.str, content_id); + out->SetFormat("%s/%s", root.Get(), content_name.str); } - void MakeContentPathDualLayered(char *path_out, ContentId content_id, const char *root) { - char content_name[FS_MAX_PATH] = {0}; + void MakeContentPathDualLayered(PathString *out, ContentId content_id, const PathString &root) { const u16 hash = Get16BitSha256HashPrefix(content_id.uuid); const u32 hash_lower = (hash >> 4) & 0x3f; const u32 hash_upper = (hash >> 10) & 0x3f; - GetContentFileName(content_name, content_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%08X/%08X/%s", root, hash_upper, hash_lower, content_name) >= 0); + Path content_name; + GetContentFileName(content_name.str, content_id); + out->SetFormat("%s/%08X/%08X/%s", root.Get(), hash_upper, hash_lower, content_name.str); } - void MakeContentPath10BitLayered(char *path_out, ContentId content_id, const char *root) { - char content_name[FS_MAX_PATH] = {0}; + void MakeContentPath10BitLayered(PathString *out, ContentId content_id, const PathString &root) { const u32 hash = (Get16BitSha256HashPrefix(content_id.uuid) >> 6) & 0x3FF; - GetContentFileName(content_name, content_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%08X/%s", root, hash, content_name) >= 0); + + Path content_name; + GetContentFileName(content_name.str, content_id); + out->SetFormat("%s/%08X/%s", root.Get(), hash, content_name.str); } - void MakeContentPathHashByteLayered(char *path_out, ContentId content_id, const char *root) { - char content_name[FS_MAX_PATH] = {0}; + void MakeContentPathHashByteLayered(PathString *out, ContentId content_id, const PathString &root) { const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(content_id.uuid)); - GetContentFileName(content_name, content_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%08X/%s", root, hash_byte, content_name) >= 0); + + Path content_name; + GetContentFileName(content_name.str, content_id); + out->SetFormat("%s/%08X/%s", root.Get(), hash_byte, content_name.str); } - void MakePlaceHolderPathFlat(char *path_out, PlaceHolderId placeholder_id, const char *root) { - char placeholder_name[FS_MAX_PATH] = {0}; - GetPlaceHolderFileName(placeholder_name, placeholder_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%s", root, placeholder_name) >= 0); + void MakePlaceHolderPathFlat(PathString *out, PlaceHolderId placeholder_id, const PathString &root) { + Path placeholder_name; + GetPlaceHolderFileName(placeholder_name.str, placeholder_id); + out->SetFormat("%s/%s", root.Get(), placeholder_name.str); } - void MakePlaceHolderPathHashByteLayered(char *path_out, PlaceHolderId placeholder_id, const char *root) { - char placeholder_name[FS_MAX_PATH] = {0}; + void MakePlaceHolderPathHashByteLayered(PathString *out, PlaceHolderId placeholder_id, const PathString &root) { const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(placeholder_id.uuid)); - GetPlaceHolderFileName(placeholder_name, placeholder_id); - AMS_ABORT_UNLESS(snprintf(path_out, ams::fs::EntryNameLengthMax, "%s/%08X/%s", root, hash_byte, placeholder_name) >= 0); + + Path placeholder_name; + GetPlaceHolderFileName(placeholder_name.str, placeholder_id); + out->SetFormat("%s/%08X/%s", root.Get(), hash_byte, placeholder_name.str); } } diff --git a/stratosphere/ncm/source/ncm_make_path.hpp b/stratosphere/ncm/source/ncm_make_path.hpp index cc316ad28..510f380e0 100644 --- a/stratosphere/ncm/source/ncm_make_path.hpp +++ b/stratosphere/ncm/source/ncm_make_path.hpp @@ -20,12 +20,12 @@ namespace ams::ncm::path { - void MakeContentPathFlat(char *out_path, ContentId content_id, const char *root); - void MakeContentPathHashByteLayered(char *out_path, ContentId content_id, const char *root); - void MakeContentPath10BitLayered(char *out_path, ContentId content_id, const char *root); - void MakeContentPathDualLayered(char *out_path, ContentId content_id, const char *root); + void MakeContentPathFlat(PathString *out, ContentId content_id, const PathString &root); + void MakeContentPathHashByteLayered(PathString *out, ContentId content_id, const PathString &root); + void MakeContentPath10BitLayered(PathString *out, ContentId content_id, const PathString &root); + void MakeContentPathDualLayered(PathString *out, ContentId content_id, const PathString &root); - void MakePlaceHolderPathFlat(char *out_path, PlaceHolderId placeholder_id, const char *root); - void MakePlaceHolderPathHashByteLayered(char *out_path, PlaceHolderId placeholder_id, const char *root); + void MakePlaceHolderPathFlat(PathString *out, PlaceHolderId placeholder_id, const PathString &root); + void MakePlaceHolderPathHashByteLayered(PathString *out, PlaceHolderId placeholder_id, const PathString &root); } diff --git a/stratosphere/ncm/source/ncm_path_utils.cpp b/stratosphere/ncm/source/ncm_path_utils.cpp index 0b4df999f..998dc12e5 100644 --- a/stratosphere/ncm/source/ncm_path_utils.cpp +++ b/stratosphere/ncm/source/ncm_path_utils.cpp @@ -19,22 +19,12 @@ namespace ams::ncm::path { - void GetContentMetaPath(char *out, ContentId content_id, MakeContentPathFunc path_func, const char *root_path) { - char tmp_path[ams::fs::EntryNameLengthMax] = {0}; - char content_path[ams::fs::EntryNameLengthMax] = {0}; - path_func(content_path, content_id, root_path); - const size_t len = strnlen(content_path, ams::fs::EntryNameLengthMax); - const size_t len_no_extension = len - 4; + void GetContentMetaPath(PathString *out, ContentId content_id, MakeContentPathFunc path_func, const PathString &root_path) { + PathString content_path; + path_func(std::addressof(content_path), content_id, root_path); - AMS_ABORT_UNLESS(len_no_extension <= len); - AMS_ABORT_UNLESS(len_no_extension < ams::fs::EntryNameLengthMax); - - strncpy(tmp_path, content_path, len_no_extension); - memcpy(out, tmp_path, ams::fs::EntryNameLengthMax); - const size_t out_len = strnlen(out, ams::fs::EntryNameLengthMax); - - AMS_ABORT_UNLESS(out_len + 9 < ams::fs::EntryNameLengthMax); - strncat(out, ".cnmt.nca", 0x2ff - out_len); + out->Set(content_path.GetSubstring(0, content_path.GetLength() - 4)); + out->Append(".cnmt.nca"); } void GetContentFileName(char *out, ContentId content_id) { diff --git a/stratosphere/ncm/source/ncm_path_utils.hpp b/stratosphere/ncm/source/ncm_path_utils.hpp index b2663710f..edbbd3c21 100644 --- a/stratosphere/ncm/source/ncm_path_utils.hpp +++ b/stratosphere/ncm/source/ncm_path_utils.hpp @@ -20,17 +20,15 @@ namespace ams::ncm::path { - inline void GetContentRootPath(char *out_content_root, const char *root_path) { - /* TODO: Replace with BoundedString? */ - AMS_ABORT_UNLESS(snprintf(out_content_root, ams::fs::EntryNameLengthMax, "%s%s", root_path, "/registered") >= 0); + inline void GetContentRootPath(PathString *content_root, const PathString &root_path) { + content_root->SetFormat("%s%s", root_path.Get(), "/registered"); } - inline void GetPlaceHolderRootPath(char *out_placeholder_root, const char *root_path) { - /* TODO: Replace with BoundedString? */ - AMS_ABORT_UNLESS(snprintf(out_placeholder_root, FS_MAX_PATH, "%s%s", root_path, "/placehld") >= 0); + inline void GetPlaceHolderRootPath(PathString *placeholder_root, const PathString &root_path) { + placeholder_root->SetFormat("%s%s", root_path.Get(), "/placehld"); } - void GetContentMetaPath(char *out, ContentId content_id, MakeContentPathFunc path_func, const char *root_path); + void GetContentMetaPath(PathString *out, ContentId content_id, MakeContentPathFunc path_func, const PathString &root_path); void GetContentFileName(char *out, ContentId content_id); void GetPlaceHolderFileName(char *out, PlaceHolderId placeholder_id); bool IsNcaPath(const char *path); diff --git a/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp index b2c797c30..145125cb2 100644 --- a/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp +++ b/stratosphere/ncm/source/ncm_read_only_content_storage_impl.cpp @@ -20,12 +20,10 @@ namespace ams::ncm { - Result ReadOnlyContentStorageImpl::Initialize(const char *root_path, MakeContentPathFunc content_path_func) { + Result ReadOnlyContentStorageImpl::Initialize(const char *path, MakeContentPathFunc content_path_func) { R_TRY(this->EnsureEnabled()); - const size_t root_path_len = strnlen(root_path, ams::fs::EntryNameLengthMax); - AMS_ABORT_UNLESS(root_path_len < ams::fs::EntryNameLengthMax); - strncpy(this->root_path, root_path, FS_MAX_PATH-2); + this->root_path = PathString(path); this->make_content_path_func = *content_path_func; return ResultSuccess(); } @@ -61,14 +59,14 @@ namespace ams::ncm { Result ReadOnlyContentStorageImpl::Has(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - this->make_content_path_func(content_path, content_id, this->root_path); + PathString content_path; + this->make_content_path_func(std::addressof(content_path), content_id, this->root_path); bool has = false; R_TRY(fs::HasFile(&has, content_path)); if (!has) { - path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + path::GetContentMetaPath(std::addressof(content_path), content_id, this->make_content_path_func, this->root_path); R_TRY(fs::HasFile(&has, content_path)); } @@ -79,19 +77,19 @@ namespace ams::ncm { Result ReadOnlyContentStorageImpl::GetPath(sf::Out out, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; + PathString content_path; + path::GetContentMetaPath(std::addressof(content_path), content_id, this->make_content_path_func, this->root_path); + bool is_content_meta_file = false; - - path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); R_TRY(fs::HasFile(&is_content_meta_file, content_path)); if (!is_content_meta_file) { - this->make_content_path_func(content_path, content_id, this->root_path); + this->make_content_path_func(std::addressof(content_path), content_id, this->root_path); } - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, content_path)); - out.SetValue(Path::Encode(common_path)); + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, content_path)); + out.SetValue(Path::Encode(common_path.str)); return ResultSuccess(); } @@ -119,14 +117,14 @@ namespace ams::ncm { Result ReadOnlyContentStorageImpl::GetSizeFromContentId(sf::Out out_size, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - bool is_content_file = false; + PathString content_path; + this->make_content_path_func(std::addressof(content_path), content_id, this->root_path); - this->make_content_path_func(content_path, content_id, this->root_path); + bool is_content_file = false; R_TRY(fs::HasFile(&is_content_file, content_path)); if (!is_content_file) { - path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + path::GetContentMetaPath(std::addressof(content_path), content_id, this->make_content_path_func, this->root_path); } struct stat st; @@ -153,14 +151,14 @@ namespace ams::ncm { R_UNLESS(offset <= std::numeric_limits::max(), ncm::ResultInvalidOffset()); R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - bool is_content_file = false; + PathString content_path; + this->make_content_path_func(std::addressof(content_path), content_id, this->root_path); - this->make_content_path_func(content_path, content_id, this->root_path); + bool is_content_file = false; R_TRY(fs::HasFile(&is_content_file, content_path)); if (!is_content_file) { - path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + path::GetContentMetaPath(std::addressof(content_path), content_id, this->make_content_path_func, this->root_path); } FILE *f = nullptr; @@ -192,18 +190,18 @@ namespace ams::ncm { Result ReadOnlyContentStorageImpl::GetRightsIdFromContentId(sf::Out out_rights_id, ContentId content_id) { R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; - char common_path[FS_MAX_PATH] = {0}; - bool is_content_meta_file = false; + PathString content_path; + path::GetContentMetaPath(std::addressof(content_path), content_id, this->make_content_path_func, this->root_path); - path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + bool is_content_meta_file = false; R_TRY(fs::HasFile(&is_content_meta_file, content_path)); if (!is_content_meta_file) { - this->make_content_path_func(content_path, content_id, this->root_path); + this->make_content_path_func(std::addressof(content_path), content_id, this->root_path); } - R_TRY(fs::ConvertToFsCommonPath(common_path, ams::fs::EntryNameLengthMax, content_path)); + Path common_path; + R_TRY(fs::ConvertToFsCommonPath(common_path.str, ams::fs::EntryNameLengthMax, content_path)); ncm::RightsId rights_id; R_TRY(GetRightsId(&rights_id, common_path));