mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
ncm: Use PathString and Path
This commit is contained in:
parent
cdf0445982
commit
4e29d98e22
13 changed files with 195 additions and 198 deletions
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Reference in a new issue