ncm: Use PathString and Path

This commit is contained in:
Adubbz 2020-03-04 15:21:20 +11:00
parent cdf0445982
commit 4e29d98e22
13 changed files with 195 additions and 198 deletions

View file

@ -39,4 +39,7 @@ namespace ams::ncm {
using PathString = kvdb::BoundedString<fs::EntryNameLengthMax>;
using MakeContentPathFunc = void (*)(PathString *out, ContentId content_id, const PathString &root);
using MakePlaceHolderPathFunc = void (*)(PathString *out, PlaceHolderId placeholder_id, const PathString &root);
}

View file

@ -145,9 +145,6 @@ namespace ams::ncm {
static_assert(sizeof(std::is_pod<ContentInfo>::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

View file

@ -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();
}

View file

@ -34,7 +34,7 @@ namespace ams::ncm::impl {
static constexpr size_t MaxCaches = 0x2;
std::array<CacheEntry, MaxCaches> 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);

View file

@ -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<bool> 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<bool> 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<Path> 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<Path> 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<u32> out_count, const sf::OutArray<PlaceHolderId> &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<u32> 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<s32>::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<u64> 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<s64>::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<ncm::RightsId> 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));

View file

@ -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<PlaceHolderId> out) override;

View file

@ -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();

View file

@ -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();

View file

@ -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<u32>(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<u32>(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);
}
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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);

View file

@ -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<bool> 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<Path> 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<u64> 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<s64>::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<ncm::RightsId> 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));