mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-11-04 05:11:18 +01:00 
			
		
		
		
	Implement the NCM sysmodule (closes #91)
* Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Implement NCM * Modernize ncm_main * Remove unnecessary smExit * Give access to svcCallSecureMonitor * Stack size bump * Fix incorrect setup for NandUser's content storage entry * Fix a potential data abort when flushing the placeholder accessor cache * Fix HasFile and HasDirectory * Use r+b, not w+b * Misc fixes * errno begone * Fixed more stdio error handling * More main fixes * Various command improvements * Make dispatch tables great again * Fix logic inversion * Fixed content path generation * Bump heap size, fix CleanupAllPlaceHolder * Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes * Fixed placeholder/content deletion * Fixed incorrect content manager destruction * Prevent automatic placeholder creation on open * Fixed List implementation. Also lots of debug logging. * Removed debug code * Added a scope guard for WritePlaceHolder * Manually prevent placeholder/content appending * Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. * Always cache placeholder file. Switch to ftell for preventing appending * Universally use EnsureEnabled * Abstract away file writing logic * Misc cleanup * Refactor placeholder cacheing * Remove debug code (again) * Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. * Misc changes * Fixed file modes * Fixed ContentId/PlaceHolderId alignment * Improved type safety * Fixed reinitialization * Fixed doubleup on path creation * Remove debug code * Fixed 1.0.0 booting * Correct amount of add on content * Correct main thread stack size * lr: Introducing registered data * Reorder stratosphere Makefile * Move results to libstrat * lr: Cleanup lr_redirection * lr: lr_manager tweaks * lr: Imrpoved path handling and adjust ResolveAddOnContentPath order * lr: Organise types * Add eof newlines * lr: Eliminate unnecessary vars * lr: Unnecessary vars 2 electric boogaloo * lr: Various helpers * lr: RegisteredLocationResolver helpers * ncm: Move ncm_types to libstrat * ncm: Misc cleanup * Updated AddOnContentLocationResolver and RegisteredLocationResolver to 9.0.0 * Finished updating lr to 9.0.0 * Updated NCM to 9.0.0 * Fix libstrat includes * Fixed application launching * title_id_2 -> owner_tid * Updated to new-ipc * Change to using pure virtuals * Title Id -> Program Id * Fixed compilation against master * std::scoped_lock<> -> std::scoped_lock * Adopted R_UNLESS and R_CONVERT * Prefix namespace to Results * Adopt std::numeric_limits * Fixed incorrect error handling in ReadFile * Adopted AMS_ABORT_UNLESS * Adopt util::GenerateUuid() * Syntax improvements * ncm_types: Address review * Address more review comments * Updated copyrights * Address more feedback * More feedback addressed * More changes * Move dispatch tables out of interface files * Addressed remaining comments * lr: move into libstratosphere * ncm: Fix logic inversion * lr: Add comments * lr: Remove whitespace * ncm: Start addressing feedback * ncm: Cleanup InitializeContentManager * lr: support client-side usage * lr_service -> lr_api * ncm: Begin refactoring content manager * ncm: More content manager improvements * ncm: Content manager mount improvements * ldr: use lr bindings * lr bindings usage: minor fixes * ncm/lr: Pointer placement * ncm: placeholder accessor cleanup * ncm: minor fixes * ncm: refactor rights cache * ncm: content meta database cleanup * ncm: move content meta database impl out of interface file * ncm: Use const ContentMetaKey & * ncm: fix other non-const ContentMetaKey references * ncm: content meta database cleanup * ncm: content storage fixes for 2.0.0 * ncm: add missing end of file newlines * ncm: implement ContentMetaReader * ncm: client-side api * ncm: trim trailing spaces * ncm: FS_MAX_PATH-1 -> fs::EntryNameLengthMax * ncm: Use PathString and Path * fs: implement accessor wrappers for ncm * fs: implement user fs wrappers * fs: add MountSdCard * ncm: move to content manager impl * ncm: fix up main * kvdb: use fs:: * fs: Add wrappers needed for ncm * ncm: use fs bindings, other refactoring * ncm: minor fixes * fsa: fix ReadFile without size output * fs: add substorage, rom path tool * ncm: fix dangling fsdev usage * fs: fix bug in Commit * fs: fixed incorrect mode check * fs: implement Mount(System)Data * ncm: don't delete hos * results: add R_SUCCEED_IF * ams-except-ncm: use R_SUCCEED_IF * ncm: added comments * ncm: fix api definitions * ncm: use R_SUCCEED_IF * pm: think of the savings * ncm: employ kernel strats * ncm: Nintendo has 5 MiB of heap. Give ourselves 4 to be safe, pending analysis * ncm: refactor IDs, split types header into many headers * ams.mitm: use fs bindings instead of stdio * fs: SystemData uses SystemDataId * ncm: improve meta-db accuracy * ncm: inline getlatestkey * fs: improve UnsupportedOperation results * fs: modernize mount utils * ams: misc fixes for merge-errors * fs: improve unsupportedoperation results * git subrepo pull emummc subrepo: subdir: "emummc" merged: "d12dd546" upstream: origin: "https://github.com/m4xw/emuMMC" branch: "develop" commit: "d12dd546" git-subrepo: version: "0.4.1" origin: "???" commit: "???" * util: add boundedmap * ncm: minor style fixes * ncm: don't unmount if mounting fails * lr: bug fixes * ncm: implement ncm.for-initialize + ncm.for-safemode * lr: ncm::ProgramId::Invalid -> ncm::InvalidProgramId * ncm: fix open directory mode on 1.0.0 * ncm: fix fs use, implement more of < 4.0.0 for-initialize/safemode * ncm: implement packagedcontent -> content for building metadb * ncm: fix save data flag management * ncm: address some review suggestions (thanks @leoetlino!) * updater: use fs bindings * fs: implement MountCode * fs: prefer make_unique to operator new * ncm: implement remaining ContentMetaDatabaseBuilder functionality Co-authored-by: Michael Scire <SciresM@gmail.com>
This commit is contained in:
		
							parent
							
								
									83aa6133ee
								
							
						
					
					
						commit
						aec0f45bdb
					
				@ -262,8 +262,8 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
        R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
 | 
					        R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If auto-cleared, we can succeed immediately. */
 | 
					        /* If auto-cleared, we can succeed immediately. */
 | 
				
			||||||
        R_UNLESS(entry.manually_cleared,   ResultSuccess());
 | 
					        R_SUCCEED_IF(!entry.manually_cleared);
 | 
				
			||||||
        R_UNLESS(entry.needs_clear,        ResultSuccess());
 | 
					        R_SUCCEED_IF(!entry.needs_clear);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Clear and enable. */
 | 
					        /* Clear and enable. */
 | 
				
			||||||
        entry.needs_clear = false;
 | 
					        entry.needs_clear = false;
 | 
				
			||||||
@ -277,8 +277,8 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
        R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
 | 
					        R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If auto-cleared, we can succeed immediately. */
 | 
					        /* If auto-cleared, we can succeed immediately. */
 | 
				
			||||||
        R_UNLESS(entry.manually_cleared,   ResultSuccess());
 | 
					        R_SUCCEED_IF(!entry.manually_cleared);
 | 
				
			||||||
        R_UNLESS(entry.needs_clear,        ResultSuccess());
 | 
					        R_SUCCEED_IF(!entry.needs_clear);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Clear and set priority. */
 | 
					        /* Clear and set priority. */
 | 
				
			||||||
        entry.needs_clear = false;
 | 
					        entry.needs_clear = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -832,7 +832,7 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
        L1PageTableEntry *l1_entry = impl.GetL1Entry(virt_addr);
 | 
					        L1PageTableEntry *l1_entry = impl.GetL1Entry(virt_addr);
 | 
				
			||||||
        if (l1_entry->IsBlock()) {
 | 
					        if (l1_entry->IsBlock()) {
 | 
				
			||||||
            /* If our block size is too big, don't bother. */
 | 
					            /* If our block size is too big, don't bother. */
 | 
				
			||||||
            R_UNLESS(block_size < L1BlockSize, ResultSuccess());
 | 
					            R_SUCCEED_IF(block_size >= L1BlockSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Get the addresses we're working with. */
 | 
					            /* Get the addresses we're working with. */
 | 
				
			||||||
            const KProcessAddress block_virt_addr  = util::AlignDown(GetInteger(virt_addr), L1BlockSize);
 | 
					            const KProcessAddress block_virt_addr  = util::AlignDown(GetInteger(virt_addr), L1BlockSize);
 | 
				
			||||||
@ -859,10 +859,10 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If we don't have an l1 table, we're done. */
 | 
					        /* If we don't have an l1 table, we're done. */
 | 
				
			||||||
        R_UNLESS(l1_entry->IsTable(), ResultSuccess());
 | 
					        R_SUCCEED_IF(!l1_entry->IsTable());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* We want to separate L2 contiguous blocks into L2 blocks, so check that our size permits that. */
 | 
					        /* We want to separate L2 contiguous blocks into L2 blocks, so check that our size permits that. */
 | 
				
			||||||
        R_UNLESS(block_size < L2ContiguousBlockSize, ResultSuccess());
 | 
					        R_SUCCEED_IF(block_size >= L2ContiguousBlockSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        L2PageTableEntry *l2_entry = impl.GetL2Entry(l1_entry, virt_addr);
 | 
					        L2PageTableEntry *l2_entry = impl.GetL2Entry(l1_entry, virt_addr);
 | 
				
			||||||
        if (l2_entry->IsBlock()) {
 | 
					        if (l2_entry->IsBlock()) {
 | 
				
			||||||
@ -878,7 +878,7 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* We want to separate L2 blocks into L3 contiguous blocks, so check that our size permits that. */
 | 
					            /* We want to separate L2 blocks into L3 contiguous blocks, so check that our size permits that. */
 | 
				
			||||||
            R_UNLESS(block_size < L2BlockSize, ResultSuccess());
 | 
					            R_SUCCEED_IF(block_size >= L2BlockSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Get the addresses we're working with. */
 | 
					            /* Get the addresses we're working with. */
 | 
				
			||||||
            const KProcessAddress block_virt_addr  = util::AlignDown(GetInteger(virt_addr), L2BlockSize);
 | 
					            const KProcessAddress block_virt_addr  = util::AlignDown(GetInteger(virt_addr), L2BlockSize);
 | 
				
			||||||
@ -905,10 +905,10 @@ namespace ams::kern::arch::arm64 {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If we don't have an L3 table, we're done. */
 | 
					        /* If we don't have an L3 table, we're done. */
 | 
				
			||||||
        R_UNLESS(l2_entry->IsTable(), ResultSuccess());
 | 
					        R_SUCCEED_IF(!l2_entry->IsTable());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* We want to separate L3 contiguous blocks into L2 blocks, so check that our size permits that. */
 | 
					        /* We want to separate L3 contiguous blocks into L2 blocks, so check that our size permits that. */
 | 
				
			||||||
        R_UNLESS(block_size < L3ContiguousBlockSize, ResultSuccess());
 | 
					        R_SUCCEED_IF(block_size >= L3ContiguousBlockSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* If we're contiguous, try to separate. */
 | 
					        /* If we're contiguous, try to separate. */
 | 
				
			||||||
        L3PageTableEntry *l3_entry = impl.GetL3Entry(l2_entry, virt_addr);
 | 
					        L3PageTableEntry *l3_entry = impl.GetL3Entry(l2_entry, virt_addr);
 | 
				
			||||||
 | 
				
			|||||||
@ -257,7 +257,7 @@ namespace ams::kern::board::nintendo::nx {
 | 
				
			|||||||
                            const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
 | 
					                            const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
 | 
				
			||||||
                            this->state[i] |= clear_bit;
 | 
					                            this->state[i] |= clear_bit;
 | 
				
			||||||
                            out[num_reserved++] = static_cast<u8>(BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit));
 | 
					                            out[num_reserved++] = static_cast<u8>(BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit));
 | 
				
			||||||
                            R_UNLESS(num_reserved != num_desired, ResultSuccess());
 | 
					                            R_SUCCEED_IF(num_reserved == num_desired);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -211,7 +211,9 @@ namespace ams::kern {
 | 
				
			|||||||
        /* Validate this is a capability we can act on. */
 | 
					        /* Validate this is a capability we can act on. */
 | 
				
			||||||
        const auto type = GetCapabilityType(cap);
 | 
					        const auto type = GetCapabilityType(cap);
 | 
				
			||||||
        R_UNLESS(type != CapabilityType::Invalid, svc::ResultInvalidArgument());
 | 
					        R_UNLESS(type != CapabilityType::Invalid, svc::ResultInvalidArgument());
 | 
				
			||||||
        R_UNLESS(type != CapabilityType::Padding, ResultSuccess());
 | 
					
 | 
				
			||||||
 | 
					        /* If the type is padding, we have no work to do. */
 | 
				
			||||||
 | 
					        R_SUCCEED_IF(type == CapabilityType::Padding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check that we haven't already processed this capability. */
 | 
					        /* Check that we haven't already processed this capability. */
 | 
				
			||||||
        const auto flag = GetCapabilityFlag(type);
 | 
					        const auto flag = GetCapabilityFlag(type);
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@ namespace ams::kern {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Result KPageGroup::AddBlock(KVirtualAddress addr, size_t num_pages) {
 | 
					    Result KPageGroup::AddBlock(KVirtualAddress addr, size_t num_pages) {
 | 
				
			||||||
        /* Succeed immediately if we're adding no pages. */
 | 
					        /* Succeed immediately if we're adding no pages. */
 | 
				
			||||||
        R_UNLESS(num_pages != 0, ResultSuccess());
 | 
					        R_SUCCEED_IF(num_pages == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check for overflow. */
 | 
					        /* Check for overflow. */
 | 
				
			||||||
        MESOSPHERE_ASSERT(addr < addr + num_pages * PageSize);
 | 
					        MESOSPHERE_ASSERT(addr < addr + num_pages * PageSize);
 | 
				
			||||||
@ -46,7 +46,7 @@ namespace ams::kern {
 | 
				
			|||||||
        /* Try to just append to the last block. */
 | 
					        /* Try to just append to the last block. */
 | 
				
			||||||
        if (!this->block_list.empty()) {
 | 
					        if (!this->block_list.empty()) {
 | 
				
			||||||
            auto it = --(this->block_list.end());
 | 
					            auto it = --(this->block_list.end());
 | 
				
			||||||
            R_UNLESS(!it->TryConcatenate(addr, num_pages), ResultSuccess());
 | 
					            R_SUCCEED_IF(it->TryConcatenate(addr, num_pages));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Allocate a new block. */
 | 
					        /* Allocate a new block. */
 | 
				
			||||||
 | 
				
			|||||||
@ -28,8 +28,8 @@
 | 
				
			|||||||
#include "stratosphere/dd.hpp"
 | 
					#include "stratosphere/dd.hpp"
 | 
				
			||||||
#include "stratosphere/lmem.hpp"
 | 
					#include "stratosphere/lmem.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Lots of things depend on NCM, for Program IDs. */
 | 
					/* Pull in all ID definitions from NCM. */
 | 
				
			||||||
#include "stratosphere/ncm.hpp"
 | 
					#include "stratosphere/ncm/ncm_ids.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* At this point, just include the rest alphabetically. */
 | 
					/* At this point, just include the rest alphabetically. */
 | 
				
			||||||
/* TODO: Figure out optimal order. */
 | 
					/* TODO: Figure out optimal order. */
 | 
				
			||||||
@ -41,7 +41,9 @@
 | 
				
			|||||||
#include "stratosphere/hos.hpp"
 | 
					#include "stratosphere/hos.hpp"
 | 
				
			||||||
#include "stratosphere/kvdb.hpp"
 | 
					#include "stratosphere/kvdb.hpp"
 | 
				
			||||||
#include "stratosphere/ldr.hpp"
 | 
					#include "stratosphere/ldr.hpp"
 | 
				
			||||||
 | 
					#include "stratosphere/lr.hpp"
 | 
				
			||||||
#include "stratosphere/map.hpp"
 | 
					#include "stratosphere/map.hpp"
 | 
				
			||||||
 | 
					#include "stratosphere/ncm.hpp"
 | 
				
			||||||
#include "stratosphere/patcher.hpp"
 | 
					#include "stratosphere/patcher.hpp"
 | 
				
			||||||
#include "stratosphere/pm.hpp"
 | 
					#include "stratosphere/pm.hpp"
 | 
				
			||||||
#include "stratosphere/reg.hpp"
 | 
					#include "stratosphere/reg.hpp"
 | 
				
			||||||
 | 
				
			|||||||
@ -15,8 +15,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "../os/os_common_types.hpp"
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
#include "../ncm/ncm_types.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::cfg {
 | 
					namespace ams::cfg {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,9 +15,9 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "../os/os_common_types.hpp"
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
#include "../ncm/ncm_types.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
#include "../sf/sf_buffer_tags.hpp"
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::dmnt::cheat {
 | 
					namespace ams::dmnt::cheat {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,8 +16,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vapours.hpp>
 | 
					#include <vapours.hpp>
 | 
				
			||||||
#include "../ncm/ncm_types.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
#include "../sf/sf_buffer_tags.hpp"
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fatal {
 | 
					namespace ams::fatal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,11 +19,31 @@
 | 
				
			|||||||
#include <stratosphere/fs/fsa/fs_ifile.hpp>
 | 
					#include <stratosphere/fs/fsa/fs_ifile.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
 | 
					#include <stratosphere/fs/fsa/fs_idirectory.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
 | 
					#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/impl/fs_filesystem_proxy_type.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fsa/fs_registrar.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_remote_filesystem.hpp>
 | 
					#include <stratosphere/fs/fs_remote_filesystem.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_readonly_filesystem_adapter.hpp>
 | 
					#include <stratosphere/fs/fs_readonly_filesystem_adapter.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_istorage.hpp>
 | 
					#include <stratosphere/fs/fs_istorage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_substorage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_memory_storage.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_remote_storage.hpp>
 | 
					#include <stratosphere/fs/fs_remote_storage.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_file_storage.hpp>
 | 
					#include <stratosphere/fs/fs_file_storage.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_query_range.hpp>
 | 
					#include <stratosphere/fs/fs_query_range.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/impl/fs_common_mount_name.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_mount.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_path_tool.hpp>
 | 
					#include <stratosphere/fs/fs_path_tool.hpp>
 | 
				
			||||||
#include <stratosphere/fs/fs_path_utils.hpp>
 | 
					#include <stratosphere/fs/fs_path_utils.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_romfs_filesystem.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/impl/fs_data.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_system_data.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_bis.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_code.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_content.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_game_card.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_sd_card.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_signed_system_partition.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_save_data_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_save_data_management.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_save_data_transaction.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_system_save_data.hpp>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										58
									
								
								libstratosphere/include/stratosphere/fs/fs_bis.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libstratosphere/include/stratosphere/fs/fs_bis.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_common.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_istorage.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   enum class BisPartitionId {
 | 
				
			||||||
 | 
					       /* Boot0 */
 | 
				
			||||||
 | 
					       BootPartition1Root =  0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       /* Boot1 */
 | 
				
			||||||
 | 
					       BootPartition2Root = 10,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       /* Non-Boot */
 | 
				
			||||||
 | 
					       UserDataRoot                     = 20,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part1       = 21,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part2       = 22,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part3       = 23,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part4       = 24,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part5       = 25,
 | 
				
			||||||
 | 
					       BootConfigAndPackage2Part6       = 26,
 | 
				
			||||||
 | 
					       CalibrationBinary                = 27,
 | 
				
			||||||
 | 
					       CalibrationFile                  = 28,
 | 
				
			||||||
 | 
					       SafeMode                         = 29,
 | 
				
			||||||
 | 
					       User                             = 30,
 | 
				
			||||||
 | 
					       System                           = 31,
 | 
				
			||||||
 | 
					       SystemProperEncryption           = 32,
 | 
				
			||||||
 | 
					       SystemProperPartition            = 33,
 | 
				
			||||||
 | 
					       SignedSystemPartitionOnSafeMode  = 34,
 | 
				
			||||||
 | 
					   };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   const char *GetBisMountName(BisPartitionId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Result MountBis(BisPartitionId id, const char *root_path);
 | 
				
			||||||
 | 
					   Result MountBis(const char *name, BisPartitionId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   void SetBisRootForHost(BisPartitionId id, const char *root_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Result OpenBisPartition(std::unique_ptr<fs::IStorage> *out, BisPartitionId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Result InvalidateBisCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								libstratosphere/include/stratosphere/fs/fs_code.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								libstratosphere/include/stratosphere/fs/fs_code.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountCode(const char *name, const char *path, ncm::ProgramId program_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -15,13 +15,34 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vapours.hpp>
 | 
					#include <vapours.hpp>
 | 
				
			||||||
#include "../os.hpp"
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
#include "../ncm.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
#include "../sf.hpp"
 | 
					#include <stratosphere/sf.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fs {
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* TODO: Better place for this? */
 | 
					    struct Int64 {
 | 
				
			||||||
    constexpr inline size_t MountNameLengthMax = 15;
 | 
					        u32 low;
 | 
				
			||||||
 | 
					        u32 high;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					        constexpr ALWAYS_INLINE void Set(s64 v) {
 | 
				
			||||||
 | 
					            this->low  = static_cast<u32>((v & static_cast<u64>(0x00000000FFFFFFFFul)) >>  0);
 | 
				
			||||||
 | 
					            this->high = static_cast<u32>((v & static_cast<u64>(0xFFFFFFFF00000000ul)) >> 32);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr ALWAYS_INLINE s64 Get() const {
 | 
				
			||||||
 | 
					            return (static_cast<s64>(this->high) << 32) | (static_cast<s64>(this->low));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr ALWAYS_INLINE Int64 &operator=(s64 v) {
 | 
				
			||||||
 | 
					            this->Set(v);
 | 
				
			||||||
 | 
					            return *this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr ALWAYS_INLINE operator s64() const {
 | 
				
			||||||
 | 
					            return this->Get();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<Int64>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								libstratosphere/include/stratosphere/fs/fs_content.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								libstratosphere/include/stratosphere/fs/fs_content.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum ContentType {
 | 
				
			||||||
 | 
					        ContentType_Meta    = 0,
 | 
				
			||||||
 | 
					        ContentType_Control = 1,
 | 
				
			||||||
 | 
					        ContentType_Manual  = 2,
 | 
				
			||||||
 | 
					        ContentType_Logo    = 3,
 | 
				
			||||||
 | 
					        ContentType_Data    = 4,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountContent(const char *name, const char *path, ContentType content_type);
 | 
				
			||||||
 | 
					    Result MountContent(const char *name, const char *path, ncm::ProgramId id, ContentType content_type);
 | 
				
			||||||
 | 
					    Result MountContent(const char *name, const char *path, ncm::DataId id, ContentType content_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class ContentStorageId : u32 {
 | 
				
			||||||
 | 
					        System = 0,
 | 
				
			||||||
 | 
					        User   = 1,
 | 
				
			||||||
 | 
					        SdCard = 2,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline const char * const ContentStorageDirectoryName = "Contents";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *GetContentStorageMountName(ContentStorageId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountContentStorage(ContentStorageId id);
 | 
				
			||||||
 | 
					    Result MountContentStorage(const char *name, ContentStorageId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_dbm_rom_types.hpp"
 | 
				
			||||||
 | 
					#include "fs_dbm_rom_path_tool.hpp"
 | 
				
			||||||
 | 
					#include "fs_dbm_rom_key_value_storage.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class HierarchicalRomFileTable {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            using Position = u32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct FindPosition {
 | 
				
			||||||
 | 
					                Position next_dir;
 | 
				
			||||||
 | 
					                Position next_file;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<FindPosition>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using DirectoryInfo = RomDirectoryInfo;
 | 
				
			||||||
 | 
					            using FileInfo      = RomFileInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr RomFileId ConvertToFileId(Position pos) {
 | 
				
			||||||
 | 
					                return static_cast<RomFileId>(pos);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            static constexpr inline Position InvalidPosition = ~Position();
 | 
				
			||||||
 | 
					            static constexpr inline Position RootPosition = 0;
 | 
				
			||||||
 | 
					            static constexpr inline size_t ReservedDirectoryCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr RomDirectoryId ConvertToDirectoryId(Position pos) {
 | 
				
			||||||
 | 
					                return static_cast<RomDirectoryId>(pos);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr Position ConvertToPosition(RomDirectoryId id) {
 | 
				
			||||||
 | 
					                return static_cast<Position>(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static_assert(std::is_same<RomDirectoryId, RomFileId>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct RomDirectoryEntry {
 | 
				
			||||||
 | 
					                Position next;
 | 
				
			||||||
 | 
					                Position dir;
 | 
				
			||||||
 | 
					                Position file;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<RomDirectoryEntry>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct RomFileEntry {
 | 
				
			||||||
 | 
					                Position next;
 | 
				
			||||||
 | 
					                FileInfo info;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<RomFileEntry>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr inline u32 MaxKeyLength = RomPathTool::MaxPathLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            template<typename ImplKeyType, typename ClientKeyType, typename ValueType>
 | 
				
			||||||
 | 
					            class EntryMapTable : public RomKeyValueStorage<ImplKeyType, ValueType, MaxKeyLength> {
 | 
				
			||||||
 | 
					                public:
 | 
				
			||||||
 | 
					                    using ImplKey   = ImplKeyType;
 | 
				
			||||||
 | 
					                    using ClientKey = ClientKeyType;
 | 
				
			||||||
 | 
					                    using Value     = ValueType;
 | 
				
			||||||
 | 
					                    using Position  = HierarchicalRomFileTable::Position;
 | 
				
			||||||
 | 
					                    using Base      = RomKeyValueStorage<ImplKeyType, ValueType, MaxKeyLength>;
 | 
				
			||||||
 | 
					                public:
 | 
				
			||||||
 | 
					                    Result Add(Position *out, const ClientKeyType &key, const Value &value) {
 | 
				
			||||||
 | 
					                        return Base::AddImpl(out, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar), value);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Result Get(Position *out_pos, Value *out_val, const ClientKeyType &key) {
 | 
				
			||||||
 | 
					                        return Base::GetImpl(out_pos, out_val, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Result GetByPosition(ImplKey *out_key, Value *out_val, Position pos) {
 | 
				
			||||||
 | 
					                        return Base::GetByPosition(out_key, out_val, pos);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Result GetByPosition(ImplKey *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
 | 
				
			||||||
 | 
					                        return Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Result SetByPosition(Position pos, const Value &value) {
 | 
				
			||||||
 | 
					                        return Base::SetByPosition(pos, value);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct RomEntryKey {
 | 
				
			||||||
 | 
					                Position parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                bool IsEqual(const RomEntryKey &rhs, const void *aux_lhs, size_t aux_lhs_size, const void *aux_rhs, size_t aux_rhs_size) const {
 | 
				
			||||||
 | 
					                    if (this->parent != rhs.parent) {
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (aux_lhs_size != aux_rhs_size) {
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return RomPathTool::IsEqualPath(reinterpret_cast<const RomPathChar *>(aux_lhs), reinterpret_cast<const RomPathChar *>(aux_rhs), aux_lhs_size / sizeof(RomPathChar));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<RomEntryKey>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct EntryKey {
 | 
				
			||||||
 | 
					                RomEntryKey key;
 | 
				
			||||||
 | 
					                RomPathTool::RomEntryName name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                constexpr u32 Hash() const {
 | 
				
			||||||
 | 
					                    u32 hash = this->key.parent ^ 123456789;
 | 
				
			||||||
 | 
					                    const RomPathChar *name = this->name.path;
 | 
				
			||||||
 | 
					                    const RomPathChar *end  = name + this->name.length;
 | 
				
			||||||
 | 
					                    while (name < end) {
 | 
				
			||||||
 | 
					                        const u32 cur = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(name++)));
 | 
				
			||||||
 | 
					                        hash = ((hash >> 5) | (hash << 27)) ^ cur;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return hash;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<EntryKey>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using DirectoryEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomDirectoryEntry>;
 | 
				
			||||||
 | 
					            using FileEntryMapTable      = EntryMapTable<RomEntryKey, EntryKey, RomFileEntry>;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            DirectoryEntryMapTable dir_table;
 | 
				
			||||||
 | 
					            FileEntryMapTable file_table;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            static s64 QueryDirectoryEntryStorageSize(u32 count);
 | 
				
			||||||
 | 
					            static s64 QueryDirectoryEntryBucketStorageSize(s64 count);
 | 
				
			||||||
 | 
					            static s64 QueryFileEntryStorageSize(u32 count);
 | 
				
			||||||
 | 
					            static s64 QueryFileEntryBucketStorageSize(s64 count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static Result Format(SubStorage dir_bucket, SubStorage file_bucket);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            HierarchicalRomFileTable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            constexpr u32 GetDirectoryEntryCount() const {
 | 
				
			||||||
 | 
					                return this->dir_table.GetEntryCount();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            constexpr u32 GetFileEntryCount() const {
 | 
				
			||||||
 | 
					                return this->file_table.GetEntryCount();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Initialize(SubStorage dir_bucket, SubStorage dir_entry, SubStorage file_bucket, SubStorage file_entry);
 | 
				
			||||||
 | 
					            void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result CreateRootDirectory();
 | 
				
			||||||
 | 
					            Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path, const DirectoryInfo &info);
 | 
				
			||||||
 | 
					            Result CreateFile(RomFileId *out, const RomPathChar *path, const FileInfo &info);
 | 
				
			||||||
 | 
					            Result ConvertPathToDirectoryId(RomDirectoryId *out, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result ConvertPathToFileId(RomFileId *out, const RomPathChar *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetDirectoryInformation(DirectoryInfo *out, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result GetDirectoryInformation(DirectoryInfo *out, RomDirectoryId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result OpenFile(FileInfo *out, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result OpenFile(FileInfo *out, RomFileId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindOpen(FindPosition *out, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result FindOpen(FindPosition *out, RomDirectoryId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindNextDirectory(RomPathChar *out, FindPosition *find, size_t length);
 | 
				
			||||||
 | 
					            Result FindNextFile(RomPathChar *out, FindPosition *find, size_t length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result QueryRomFileSystemSize(s64 *out_dir_entry_size, s64 *out_file_entry_size);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            Result GetGrandParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindParentDirectoryRecursive(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, RomPathTool::PathParser *parser, const RomPathChar *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindPathRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, bool is_dir, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result FindDirectoryRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
 | 
				
			||||||
 | 
					            Result FindFileRecursive(EntryKey *out_key, RomDirectoryEntry *out_dir_entry, const RomPathChar *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result CheckSameEntryExists(const EntryKey &key, Result if_exists);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetDirectoryEntry(Position *out_pos, RomDirectoryEntry *out_entry, const EntryKey &key);
 | 
				
			||||||
 | 
					            Result GetDirectoryEntry(RomDirectoryEntry *out_entry, RomDirectoryId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetFileEntry(Position *out_pos, RomFileEntry *out_entry, const EntryKey &key);
 | 
				
			||||||
 | 
					            Result GetFileEntry(RomFileEntry *out_entry, RomFileId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetDirectoryInformation(DirectoryInfo *out, const EntryKey &key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result OpenFile(FileInfo *out, const EntryKey &key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindOpen(FindPosition *out, const EntryKey &key);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,380 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_dbm_rom_types.hpp"
 | 
				
			||||||
 | 
					#include "fs_substorage.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename KeyType, typename ValueType, size_t MaxAuxiliarySize>
 | 
				
			||||||
 | 
					    class RomKeyValueStorage {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            using Key         = KeyType;
 | 
				
			||||||
 | 
					            using Value       = ValueType;
 | 
				
			||||||
 | 
					            using Position    = u32;
 | 
				
			||||||
 | 
					            using BucketIndex = s64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct FindIndex {
 | 
				
			||||||
 | 
					                BucketIndex ind;
 | 
				
			||||||
 | 
					                Position pos;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<FindIndex>::value);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            static constexpr inline Position InvalidPosition = ~Position();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct Element {
 | 
				
			||||||
 | 
					                Key key;
 | 
				
			||||||
 | 
					                Value value;
 | 
				
			||||||
 | 
					                Position next;
 | 
				
			||||||
 | 
					                u32 size;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<Element>::value);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            s64 bucket_count;
 | 
				
			||||||
 | 
					            SubStorage bucket_storage;
 | 
				
			||||||
 | 
					            SubStorage kv_storage;
 | 
				
			||||||
 | 
					            s64 total_entry_size;
 | 
				
			||||||
 | 
					            u32 entry_count;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            static constexpr s64 QueryBucketStorageSize(s64 num) {
 | 
				
			||||||
 | 
					                return num * sizeof(Position);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr s64 QueryBucketCount(s64 size) {
 | 
				
			||||||
 | 
					                return size / sizeof(Position);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr s64 QueryKeyValueStorageSize(u32 num) {
 | 
				
			||||||
 | 
					                return num * sizeof(Element);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static Result Format(SubStorage bucket, s64 count) {
 | 
				
			||||||
 | 
					                const Position pos = InvalidPosition;
 | 
				
			||||||
 | 
					                for (s64 i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					                    R_TRY(bucket.Write(i * sizeof(pos), std::addressof(pos), sizeof(pos)));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            RomKeyValueStorage() : bucket_count(), bucket_storage(), kv_storage(), total_entry_size(), entry_count() { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Initialize(const SubStorage &bucket, s64 count, const SubStorage &kv) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(count > 0);
 | 
				
			||||||
 | 
					                this->bucket_storage = bucket;
 | 
				
			||||||
 | 
					                this->kv_storage     = kv;
 | 
				
			||||||
 | 
					                this->bucket_count   = count;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Finalize() {
 | 
				
			||||||
 | 
					                this->bucket_storage = SubStorage();
 | 
				
			||||||
 | 
					                this->kv_storage     = SubStorage();
 | 
				
			||||||
 | 
					                this->bucket_count   = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            s64 GetTotalEntrySize() const {
 | 
				
			||||||
 | 
					                return this->total_entry_size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetFreeSize(s64 *out) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					                s64 kv_size = 0;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                *out = kv_size - this->total_entry_size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            constexpr u32 GetEntryCount() const {
 | 
				
			||||||
 | 
					                return this->entry_count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Add(const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux_size <= MaxAuxiliarySize);
 | 
				
			||||||
 | 
					                Position pos;
 | 
				
			||||||
 | 
					                return this->AddImpl(std::addressof(pos), key, hash_key, aux, aux_size, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Get(Value *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux_size <= MaxAuxiliarySize);
 | 
				
			||||||
 | 
					                Position pos;
 | 
				
			||||||
 | 
					                return this->GetImpl(std::addressof(pos), out, key, hash_key, aux, aux_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindOpen(FindIndex *out) const {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                out->ind = static_cast<BucketIndex>(-1);
 | 
				
			||||||
 | 
					                out->pos = InvalidPosition;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindNext(Key *out_key, Value *out_val, FindIndex *find) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_key != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_val != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(find != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                BucketIndex ind = find->ind;
 | 
				
			||||||
 | 
					                R_UNLESS((ind < this->bucket_count) || ind == static_cast<BucketIndex>(-1), fs::ResultDbmFindKeyFinished());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                while (true) {
 | 
				
			||||||
 | 
					                    if (find->pos != InvalidPosition) {
 | 
				
			||||||
 | 
					                        Element elem;
 | 
				
			||||||
 | 
					                        R_TRY(this->ReadKeyValue(std::addressof(elem), find->pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        AMS_ASSERT(elem.next == InvalidPosition || elem.next < kv_size);
 | 
				
			||||||
 | 
					                        find->pos = elem.next;
 | 
				
			||||||
 | 
					                        *out_key = elem.key;
 | 
				
			||||||
 | 
					                        *out_val = elem.val;
 | 
				
			||||||
 | 
					                        return ResultSuccess();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    while (true) {
 | 
				
			||||||
 | 
					                        ind++;
 | 
				
			||||||
 | 
					                        if (ind == this->bucket_count) {
 | 
				
			||||||
 | 
					                            find->ind = ind;
 | 
				
			||||||
 | 
					                            find->pos = InvalidPosition;
 | 
				
			||||||
 | 
					                            return fs::ResultDbmFindKeyFinished();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        Position pos;
 | 
				
			||||||
 | 
					                        R_TRY(this->ReadBucket(std::addressof(pos), ind));
 | 
				
			||||||
 | 
					                        AMS_ASSERT(pos == InvalidPosition || pos < kv_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (pos != InvalidPosition) {
 | 
				
			||||||
 | 
					                            find->ind = ind;
 | 
				
			||||||
 | 
					                            find->pos = pos;
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            Result AddImpl(Position *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->bucket_count > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Position pos, prev_pos;
 | 
				
			||||||
 | 
					                    Element elem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const Result find_res = this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size);
 | 
				
			||||||
 | 
					                    R_UNLESS(R_FAILED(find_res),                           fs::ResultDbmAlreadyExists());
 | 
				
			||||||
 | 
					                    R_UNLESS(fs::ResultDbmKeyNotFound::Includes(find_res), find_res);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Position pos;
 | 
				
			||||||
 | 
					                R_TRY(this->AllocateEntry(std::addressof(pos), aux_size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Position next_pos;
 | 
				
			||||||
 | 
					                R_TRY(this->LinkEntry(std::addressof(next_pos), pos, hash_key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const Element elem = { key, value, next_pos, static_cast<u32>(aux_size) };
 | 
				
			||||||
 | 
					                R_TRY(this->WriteKeyValue(std::addressof(elem), pos, aux, aux_size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out = pos;
 | 
				
			||||||
 | 
					                this->entry_count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetImpl(Position *out_pos, Value *out_val, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_pos != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_val != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux     != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Position pos, prev_pos;
 | 
				
			||||||
 | 
					                Element elem;
 | 
				
			||||||
 | 
					                R_TRY(this->FindImpl(std::addressof(pos), std::addressof(prev_pos), std::addressof(elem), key, hash_key, aux, aux_size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_pos = pos;
 | 
				
			||||||
 | 
					                *out_val = elem.value;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetByPosition(Key *out_key, Value *out_val, Position pos) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_key != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_val != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Element elem;
 | 
				
			||||||
 | 
					                R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_key = elem.key;
 | 
				
			||||||
 | 
					                *out_val = elem.value;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetByPosition(Key *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_key != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_val != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_aux_size != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Element elem;
 | 
				
			||||||
 | 
					                R_TRY(this->ReadKeyValue(std::addressof(elem), out_aux, out_aux_size, pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_key = elem.key;
 | 
				
			||||||
 | 
					                *out_val = elem.value;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result SetByPosition(Position pos, const Value &value) {
 | 
				
			||||||
 | 
					                Element elem;
 | 
				
			||||||
 | 
					                R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
 | 
				
			||||||
 | 
					                elem.value = value;
 | 
				
			||||||
 | 
					                return this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            BucketIndex HashToBucket(u32 hash_key) const {
 | 
				
			||||||
 | 
					                return hash_key % this->bucket_count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FindImpl(Position *out_pos, Position *out_prev, Element *out_elem, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_pos != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_prev != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_elem != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->bucket_count > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_pos = 0;
 | 
				
			||||||
 | 
					                *out_prev = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const BucketIndex ind = HashToBucket(hash_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Position cur;
 | 
				
			||||||
 | 
					                R_TRY(this->ReadBucket(std::addressof(cur), ind));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                AMS_ASSERT(cur == InvalidPosition || cur < kv_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                u8 *buf = static_cast<u8 *>(::ams::fs::impl::Allocate(MaxAuxiliarySize));
 | 
				
			||||||
 | 
					                R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInDbmRomKeyValueStorage());
 | 
				
			||||||
 | 
					                ON_SCOPE_EXIT { ::ams::fs::impl::Deallocate(buf, MaxAuxiliarySize); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                while (true) {
 | 
				
			||||||
 | 
					                    size_t cur_aux_size;
 | 
				
			||||||
 | 
					                    R_TRY(this->ReadKeyValue(out_elem, buf, std::addressof(cur_aux_size), cur));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (key.IsEqual(out_elem->key, aux, aux_size, buf, cur_aux_size)) {
 | 
				
			||||||
 | 
					                        *out_pos = cur;
 | 
				
			||||||
 | 
					                        return ResultSuccess();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    *out_prev = cur;
 | 
				
			||||||
 | 
					                    cur = out_elem->next;
 | 
				
			||||||
 | 
					                    R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result AllocateEntry(Position *out, size_t aux_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                const size_t end_pos = this->total_entry_size + sizeof(Element) + aux_size;
 | 
				
			||||||
 | 
					                R_UNLESS(end_pos <= static_cast<size_t>(kv_size), fs::ResultDbmKeyFull());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out = static_cast<Position>(this->total_entry_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this->total_entry_size = util::AlignUp(static_cast<s64>(end_pos), s64(4));
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result LinkEntry(Position *out, Position pos, u32 hash_key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const BucketIndex ind = HashToBucket(hash_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Position next;
 | 
				
			||||||
 | 
					                R_TRY(this->ReadBucket(std::addressof(next), ind));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                AMS_ASSERT(next == InvalidPosition || next < kv_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                R_TRY(this->WriteBucket(pos, ind));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out = next;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ReadBucket(Position *out, BucketIndex ind) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(ind < this->bucket_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const s64 offset = ind * sizeof(Position);
 | 
				
			||||||
 | 
					                return this->bucket_storage.Read(offset, out, sizeof(*out));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result WriteBucket(Position pos, BucketIndex ind) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(ind < this->bucket_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const s64 offset = ind * sizeof(Position);
 | 
				
			||||||
 | 
					                return this->bucket_storage.Write(offset, std::addressof(pos), sizeof(pos));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ReadKeyValue(Element *out, Position pos) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                AMS_ASSERT(pos < kv_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return this->kv_storage.Read(pos, out, sizeof(*out));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ReadKeyValue(Element *out, void *out_aux, size_t *out_aux_size, Position pos) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(out != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_aux != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(out_aux_size != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                R_TRY(this->ReadKeyValue(out, pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_aux_size = out->size;
 | 
				
			||||||
 | 
					                if (out->size > 0) {
 | 
				
			||||||
 | 
					                    R_TRY(this->kv_storage.Read(pos + sizeof(*out), out_aux, out->size));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result WriteKeyValue(const Element *elem, Position pos, const void *aux, size_t aux_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(elem != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(aux != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s64 kv_size;
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.GetSize(std::addressof(kv_size)));
 | 
				
			||||||
 | 
					                AMS_ASSERT(pos < kv_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                R_TRY(this->kv_storage.Write(pos, elem, sizeof(*elem)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (aux != nullptr && aux_size > 0) {
 | 
				
			||||||
 | 
					                    R_TRY(this->kv_storage.Write(pos + sizeof(*elem), aux, aux_size));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										122
									
								
								libstratosphere/include/stratosphere/fs/fs_dbm_rom_path_tool.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								libstratosphere/include/stratosphere/fs/fs_dbm_rom_path_tool.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_dbm_rom_types.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace RomPathTool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline u32 MaxPathLength = 0x300;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct RomEntryName {
 | 
				
			||||||
 | 
					            size_t length;
 | 
				
			||||||
 | 
					            const RomPathChar *path;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        static_assert(std::is_pod<RomEntryName>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr void InitializeRomEntryName(RomEntryName *entry) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(entry != nullptr);
 | 
				
			||||||
 | 
					            entry->length = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsSeparator(RomPathChar c) {
 | 
				
			||||||
 | 
					            return c == RomStringTraits::DirectorySeparator;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsNullTerminator(RomPathChar c) {
 | 
				
			||||||
 | 
					            return c == RomStringTraits::NullTerminator;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsDot(RomPathChar c) {
 | 
				
			||||||
 | 
					            return c == RomStringTraits::Dot;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsCurrentDirectory(const RomEntryName &name) {
 | 
				
			||||||
 | 
					            return name.length == 1 && IsDot(name.path[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsCurrentDirectory(const RomPathChar *p, size_t length) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(p != nullptr);
 | 
				
			||||||
 | 
					            return length == 1 && IsDot(p[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsCurrentDirectory(const RomPathChar *p) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(p != nullptr);
 | 
				
			||||||
 | 
					            return IsDot(p[0]) && IsNullTerminator(p[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsParentDirectory(const RomEntryName &name) {
 | 
				
			||||||
 | 
					            return name.length == 2 && IsDot(name.path[0]) && IsDot(name.path[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsParentDirectory(const RomPathChar *p) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(p != nullptr);
 | 
				
			||||||
 | 
					            return IsDot(p[0]) && IsDot(p[1]) && IsNullTerminator(p[2]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsParentDirectory(const RomPathChar *p, size_t length) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(p != nullptr);
 | 
				
			||||||
 | 
					            return length == 2 && IsDot(p[0]) && IsDot(p[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsEqualPath(const RomPathChar *lhs, const RomPathChar *rhs, size_t length) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(lhs != nullptr);
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(rhs != nullptr);
 | 
				
			||||||
 | 
					            return std::strncmp(lhs, rhs, length) == 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomPathChar *rhs) {
 | 
				
			||||||
 | 
					            AMS_ABORT_UNLESS(rhs != nullptr);
 | 
				
			||||||
 | 
					            if (strnlen(rhs, MaxPathLength) != lhs.length) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return IsEqualPath(lhs.path, rhs, lhs.length);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsEqualName(const RomEntryName &lhs, const RomEntryName &rhs) {
 | 
				
			||||||
 | 
					            if (lhs.length != rhs.length) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return IsEqualPath(lhs.path, rhs.path, lhs.length);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Result GetParentDirectoryName(RomEntryName *out, const RomEntryName &cur, const RomPathChar *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class PathParser {
 | 
				
			||||||
 | 
					            private:
 | 
				
			||||||
 | 
					                const RomPathChar *prev_path_start;
 | 
				
			||||||
 | 
					                const RomPathChar *prev_path_end;
 | 
				
			||||||
 | 
					                const RomPathChar *next_path;
 | 
				
			||||||
 | 
					                bool finished;
 | 
				
			||||||
 | 
					            public:
 | 
				
			||||||
 | 
					                constexpr PathParser() : prev_path_start(), prev_path_end(), next_path(), finished() { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Result Initialize(const RomPathChar *path);
 | 
				
			||||||
 | 
					                void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                bool IsFinished() const;
 | 
				
			||||||
 | 
					                bool IsDirectoryPath() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Result GetAsDirectoryName(RomEntryName *out) const;
 | 
				
			||||||
 | 
					                Result GetAsFileName(RomEntryName *out) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Result GetNextDirectoryName(RomEntryName *out);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										59
									
								
								libstratosphere/include/stratosphere/fs/fs_dbm_rom_types.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libstratosphere/include/stratosphere/fs/fs_dbm_rom_types.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using RomPathChar    = char;
 | 
				
			||||||
 | 
					    using RomFileId      = s32;
 | 
				
			||||||
 | 
					    using RomDirectoryId = s32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RomFileSystemInformation {
 | 
				
			||||||
 | 
					        s64 size;
 | 
				
			||||||
 | 
					        s64 directory_bucket_offset;
 | 
				
			||||||
 | 
					        s64 directory_bucket_size;
 | 
				
			||||||
 | 
					        s64 directory_entry_offset;
 | 
				
			||||||
 | 
					        s64 directory_entry_size;
 | 
				
			||||||
 | 
					        s64 file_bucket_offset;
 | 
				
			||||||
 | 
					        s64 file_bucket_size;
 | 
				
			||||||
 | 
					        s64 file_entry_offset;
 | 
				
			||||||
 | 
					        s64 file_entry_size;
 | 
				
			||||||
 | 
					        s64 body_offset;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<RomFileSystemInformation>::value);
 | 
				
			||||||
 | 
					    static_assert(sizeof(RomFileSystemInformation) == 0x50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RomDirectoryInfo {
 | 
				
			||||||
 | 
					        /* ... */
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<RomDirectoryInfo>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RomFileInfo {
 | 
				
			||||||
 | 
					        Int64 offset;
 | 
				
			||||||
 | 
					        Int64 size;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<RomFileInfo>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace RomStringTraits {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline char DirectorySeparator = '/';
 | 
				
			||||||
 | 
					        constexpr inline char NullTerminator     = '\x00';
 | 
				
			||||||
 | 
					        constexpr inline char Dot                = '.';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,4 +22,12 @@ namespace ams::fs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    using DirectoryEntry = ::FsDirectoryEntry;
 | 
					    using DirectoryEntry = ::FsDirectoryEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct DirectoryHandle {
 | 
				
			||||||
 | 
					        void *handle;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries);
 | 
				
			||||||
 | 
					    Result GetDirectoryEntryCount(s64 *out, DirectoryHandle handle);
 | 
				
			||||||
 | 
					    void CloseDirectory(DirectoryHandle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -60,4 +60,19 @@ namespace ams::fs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static_assert(std::is_pod<WriteOption>::value && sizeof(WriteOption) == sizeof(u32));
 | 
					    static_assert(std::is_pod<WriteOption>::value && sizeof(WriteOption) == sizeof(u32));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct FileHandle {
 | 
				
			||||||
 | 
					        void *handle;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option);
 | 
				
			||||||
 | 
					    Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size);
 | 
				
			||||||
 | 
					    Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option);
 | 
				
			||||||
 | 
					    Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size);
 | 
				
			||||||
 | 
					    Result GetFileSize(s64 *out, FileHandle handle);
 | 
				
			||||||
 | 
					    Result FlushFile(FileHandle handle);
 | 
				
			||||||
 | 
					    Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option);
 | 
				
			||||||
 | 
					    Result SetFileSize(FileHandle handle, s64 size);
 | 
				
			||||||
 | 
					    int GetFileOpenMode(FileHandle handle);
 | 
				
			||||||
 | 
					    void CloseFile(FileHandle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ams::fs {
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace fsa {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class IFile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enum OpenMode {
 | 
					    enum OpenMode {
 | 
				
			||||||
        OpenMode_Read   = ::FsOpenMode_Read,
 | 
					        OpenMode_Read   = ::FsOpenMode_Read,
 | 
				
			||||||
        OpenMode_Write  = ::FsOpenMode_Write,
 | 
					        OpenMode_Write  = ::FsOpenMode_Write,
 | 
				
			||||||
@ -49,4 +55,27 @@ namespace ams::fs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    using FileTimeStampRaw = ::FsTimeStampRaw;
 | 
					    using FileTimeStampRaw = ::FsTimeStampRaw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct FileHandle;
 | 
				
			||||||
 | 
					    struct DirectoryHandle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result CreateFile(const char *path, s64 size);
 | 
				
			||||||
 | 
					    Result CreateFile(const char* path, s64 size, int option);
 | 
				
			||||||
 | 
					    Result DeleteFile(const char *path);
 | 
				
			||||||
 | 
					    Result CreateDirectory(const char *path);
 | 
				
			||||||
 | 
					    Result DeleteDirectory(const char *path);
 | 
				
			||||||
 | 
					    Result DeleteDirectoryRecursively(const char *path);
 | 
				
			||||||
 | 
					    Result RenameFile(const char *old_path, const char *new_path);
 | 
				
			||||||
 | 
					    Result RenameDirectory(const char *old_path, const char *new_path);
 | 
				
			||||||
 | 
					    Result GetEntryType(DirectoryEntryType *out, const char *path);
 | 
				
			||||||
 | 
					    Result OpenFile(FileHandle *out_file, const char *path, int mode);
 | 
				
			||||||
 | 
					    Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode);
 | 
				
			||||||
 | 
					    Result CleanDirectoryRecursively(const char *path);
 | 
				
			||||||
 | 
					    Result GetFreeSpaceSize(s64 *out, const char *path);
 | 
				
			||||||
 | 
					    Result GetTotalSpaceSize(s64 *out, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result SetConcatenationFileAttribute(const char *path);
 | 
				
			||||||
 | 
					    Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result OpenFile(FileHandle *out, std::unique_ptr<fsa::IFile> &&file, int mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										47
									
								
								libstratosphere/include/stratosphere/fs/fs_game_card.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								libstratosphere/include/stratosphere/fs/fs_game_card.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class GameCardPartition {
 | 
				
			||||||
 | 
					        Update = 0,
 | 
				
			||||||
 | 
					        Normal = 1,
 | 
				
			||||||
 | 
					        Secure = 2,
 | 
				
			||||||
 | 
					        Logo   = 3,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class GameCardPartitionRaw {
 | 
				
			||||||
 | 
					        NormalReadable,
 | 
				
			||||||
 | 
					        SecureReadable,
 | 
				
			||||||
 | 
					        RootWriteable,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class GameCardAttribute : u8 {
 | 
				
			||||||
 | 
					        AutoBootFlag                         = (1 << 0),
 | 
				
			||||||
 | 
					        HistoryEraseFlag                     = (1 << 1),
 | 
				
			||||||
 | 
					        RepairToolFlag                       = (1 << 2),
 | 
				
			||||||
 | 
					        DifferentRegionCupToTerraDeviceFlag  = (1 << 3),
 | 
				
			||||||
 | 
					        DifferentRegionCupToGlobalDeviceFlag = (1 << 4),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using GameCardHandle = u32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetGameCardHandle(GameCardHandle *out);
 | 
				
			||||||
 | 
					    Result MountGameCardPartition(const char *name, GameCardHandle handle, GameCardPartition partition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -26,21 +26,15 @@ namespace ams::fs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            virtual Result Read(s64 offset, void *buffer, size_t size) = 0;
 | 
					            virtual Result Read(s64 offset, void *buffer, size_t size) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result Write(s64 offset, const void *buffer, size_t size) {
 | 
					            virtual Result Write(s64 offset, const void *buffer, size_t size) = 0;
 | 
				
			||||||
                return fs::ResultUnsupportedOperation();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result Flush() = 0;
 | 
					            virtual Result Flush() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result SetSize(s64 size) {
 | 
					            virtual Result SetSize(s64 size) = 0;
 | 
				
			||||||
                return fs::ResultUnsupportedOperation();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetSize(s64 *out) = 0;
 | 
					            virtual Result GetSize(s64 *out) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
 | 
					            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) = 0;
 | 
				
			||||||
                return fs::ResultUnsupportedOperation();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OperateRange(OperationId op_id, s64 offset, s64 size) {
 | 
					            virtual Result OperateRange(OperationId op_id, s64 offset, s64 size) {
 | 
				
			||||||
                return this->OperateRange(nullptr, 0, op_id, offset, size, nullptr, 0);
 | 
					                return this->OperateRange(nullptr, 0, op_id, offset, size, nullptr, 0);
 | 
				
			||||||
@ -86,21 +80,31 @@ namespace ams::fs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            virtual ~ReadOnlyStorageAdapter() { /* ... */ }
 | 
					            virtual ~ReadOnlyStorageAdapter() { /* ... */ }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual Result Read(s64 offset, void *buffer, size_t size) {
 | 
					            virtual Result Read(s64 offset, void *buffer, size_t size) override {
 | 
				
			||||||
                return this->storage->Read(offset, buffer, size);
 | 
					                return this->storage->Read(offset, buffer, size);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result Flush() {
 | 
					            virtual Result Flush() override {
 | 
				
			||||||
                return this->storage->Flush();
 | 
					                return this->storage->Flush();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetSize(s64 *out) {
 | 
					            virtual Result GetSize(s64 *out) override {
 | 
				
			||||||
                return this->storage->GetSize(out);
 | 
					                return this->storage->GetSize(out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
 | 
					            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
 | 
				
			||||||
                return this->storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
 | 
					                return this->storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result Write(s64 offset, const void *buffer, size_t size) override {
 | 
				
			||||||
 | 
					                /* TODO: Better result? Is it possible to get a more specific one? */
 | 
				
			||||||
 | 
					                return fs::ResultUnsupportedOperation();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result SetSize(s64 size) override {
 | 
				
			||||||
 | 
					                /* TODO: Better result? Is it possible to get a more specific one? */
 | 
				
			||||||
 | 
					                return fs::ResultUnsupportedOperation();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using AllocateFunction   = void *(*)(size_t);
 | 
				
			||||||
 | 
					    using DeallocateFunction = void (*)(void *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SetAllocator(AllocateFunction allocator, DeallocateFunction deallocator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void *Allocate(size_t size);
 | 
				
			||||||
 | 
					        void Deallocate(void *ptr, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class Deleter {
 | 
				
			||||||
 | 
					            private:
 | 
				
			||||||
 | 
					                size_t size;
 | 
				
			||||||
 | 
					            public:
 | 
				
			||||||
 | 
					                Deleter() : size() { /* ... */ }
 | 
				
			||||||
 | 
					                explicit Deleter(size_t sz) : size(sz) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                void operator()(void *ptr) const {
 | 
				
			||||||
 | 
					                    ::ams::fs::impl::Deallocate(ptr, this->size);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        template<typename T>
 | 
				
			||||||
 | 
					        std::unique_ptr<T, Deleter> MakeUnique() {
 | 
				
			||||||
 | 
					            static_assert(std::is_pod<T>::value);
 | 
				
			||||||
 | 
					            return std::unique_ptr<T, Deleter>(static_cast<T *>(::ams::fs::impl::Allocate(sizeof(T))), Deleter(sizeof(T)));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "impl/fs_newable.hpp"
 | 
				
			||||||
 | 
					#include "fs_istorage.hpp"
 | 
				
			||||||
 | 
					#include "fs_query_range.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class MemoryStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            u8 * const buf;
 | 
				
			||||||
 | 
					            const s64 size;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            MemoryStorage(void *b, s64 sz) : buf(static_cast<u8 *>(b)), size(sz) { /* .. */ }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual Result Read(s64 offset, void *buffer, size_t size) override {
 | 
				
			||||||
 | 
					                /* Succeed immediately on zero-sized read. */
 | 
				
			||||||
 | 
					                R_SUCCEED_IF(size == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Validate arguments. */
 | 
				
			||||||
 | 
					                R_UNLESS(buffer != nullptr,                                fs::ResultNullptrArgument());
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsRangeValid(offset, size, this->size), fs::ResultOutOfRange());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Copy from memory. */
 | 
				
			||||||
 | 
					                std::memcpy(buffer, this->buf + offset, size);
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result Write(s64 offset, const void *buffer, size_t size) override {
 | 
				
			||||||
 | 
					                /* Succeed immediately on zero-sized write. */
 | 
				
			||||||
 | 
					                R_SUCCEED_IF(size == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Validate arguments. */
 | 
				
			||||||
 | 
					                R_UNLESS(buffer != nullptr,                                fs::ResultNullptrArgument());
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsRangeValid(offset, size, this->size), fs::ResultOutOfRange());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Copy to memory. */
 | 
				
			||||||
 | 
					                std::memcpy(this->buf + offset, buffer, size);
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result Flush() override {
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result GetSize(s64 *out) override {
 | 
				
			||||||
 | 
					                *out = this->size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result SetSize(s64 size) override {
 | 
				
			||||||
 | 
					                return fs::ResultUnsupportedOperationInMemoryStorageA();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
 | 
				
			||||||
 | 
					                switch (op_id) {
 | 
				
			||||||
 | 
					                    case OperationId::InvalidateCache:
 | 
				
			||||||
 | 
					                        return ResultSuccess();
 | 
				
			||||||
 | 
					                    case OperationId::QueryRange:
 | 
				
			||||||
 | 
					                        R_UNLESS(dst != nullptr,                     fs::ResultNullptrArgument());
 | 
				
			||||||
 | 
					                        R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize());
 | 
				
			||||||
 | 
					                        reinterpret_cast<QueryRangeInfo *>(dst)->Clear();
 | 
				
			||||||
 | 
					                        return ResultSuccess();
 | 
				
			||||||
 | 
					                    default:
 | 
				
			||||||
 | 
					                        return fs::ResultUnsupportedOperationInMemoryStorageB();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								libstratosphere/include/stratosphere/fs/fs_mount.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								libstratosphere/include/stratosphere/fs/fs_mount.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline size_t MountNameLengthMax = 15;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ConvertToFsCommonPath(char *dst, size_t dst_size, const char *src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Unmount(const char *mount_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -26,16 +26,25 @@ namespace ams::fs {
 | 
				
			|||||||
        constexpr inline char Dot                = '.';
 | 
					        constexpr inline char Dot                = '.';
 | 
				
			||||||
        constexpr inline char NullTerminator     = '\x00';
 | 
					        constexpr inline char NullTerminator     = '\x00';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline char AlternateDirectorySeparator = '\\';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class PathTool {
 | 
					    class PathTool {
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            static constexpr const char RootPath[] = "/";
 | 
					            static constexpr const char RootPath[] = "/";
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
 | 
					            static constexpr inline bool IsAlternateSeparator(char c) {
 | 
				
			||||||
 | 
					                return c == StringTraits::AlternateDirectorySeparator;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static constexpr inline bool IsSeparator(char c) {
 | 
					            static constexpr inline bool IsSeparator(char c) {
 | 
				
			||||||
                return c == StringTraits::DirectorySeparator;
 | 
					                return c == StringTraits::DirectorySeparator;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr inline bool IsAnySeparator(char c) {
 | 
				
			||||||
 | 
					                return IsSeparator(c) || IsAlternateSeparator(c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static constexpr inline bool IsNullTerminator(char c) {
 | 
					            static constexpr inline bool IsNullTerminator(char c) {
 | 
				
			||||||
                return c == StringTraits::NullTerminator;
 | 
					                return c == StringTraits::NullTerminator;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -56,6 +65,10 @@ namespace ams::fs {
 | 
				
			|||||||
                return IsWindowsDriveCharacter(p[0]) && IsDriveSeparator(p[1]);
 | 
					                return IsWindowsDriveCharacter(p[0]) && IsDriveSeparator(p[1]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr inline bool IsUnc(const char *p) {
 | 
				
			||||||
 | 
					                return (IsSeparator(p[0]) && IsSeparator(p[1])) || (IsAlternateSeparator(p[0]) && IsAlternateSeparator(p[1]));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static constexpr inline bool IsCurrentDirectory(const char *p) {
 | 
					            static constexpr inline bool IsCurrentDirectory(const char *p) {
 | 
				
			||||||
                return IsDot(p[0]) && (IsSeparator(p[1]) || IsNullTerminator(p[1]));
 | 
					                return IsDot(p[0]) && (IsSeparator(p[1]) || IsNullTerminator(p[1]));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "fs_common.hpp"
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include "fs_file.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fs {
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -42,4 +43,6 @@ namespace ams::fs {
 | 
				
			|||||||
    using FileQueryRangeInfo    = QueryRangeInfo;
 | 
					    using FileQueryRangeInfo    = QueryRangeInfo;
 | 
				
			||||||
    using StorageQueryRangeInfo = QueryRangeInfo;
 | 
					    using StorageQueryRangeInfo = QueryRangeInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,165 +14,217 @@
 | 
				
			|||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "fs_common.hpp"
 | 
					#include <stratosphere/fs/fs_common.hpp>
 | 
				
			||||||
#include "fsa/fs_ifile.hpp"
 | 
					#include <stratosphere/fs/impl/fs_newable.hpp>
 | 
				
			||||||
#include "fsa/fs_idirectory.hpp"
 | 
					#include <stratosphere/fs/fsa/fs_ifile.hpp>
 | 
				
			||||||
#include "fsa/fs_ifilesystem.hpp"
 | 
					#include <stratosphere/fs/fsa/fs_idirectory.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_query_range.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_path_tool.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_path_utils.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fs {
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class RemoteFile : public fsa::IFile {
 | 
					    class RemoteFile : public fsa::IFile, public impl::Newable {
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            std::unique_ptr<::FsFile> base_file;
 | 
					            ::FsFile base_file;
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            RemoteFile(::FsFile *f) : base_file(f) { /* ... */ }
 | 
					            RemoteFile(const ::FsFile &f) : base_file(f) { /* ... */ }
 | 
				
			||||||
            RemoteFile(std::unique_ptr<::FsFile> f) : base_file(std::move(f)) { /* ... */ }
 | 
					 | 
				
			||||||
            RemoteFile(::FsFile f) {
 | 
					 | 
				
			||||||
                this->base_file = std::make_unique<::FsFile>(f);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual ~RemoteFile() { fsFileClose(this->base_file.get()); }
 | 
					            virtual ~RemoteFile() { fsFileClose(std::addressof(this->base_file)); }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual Result ReadImpl(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
 | 
					            virtual Result ReadImpl(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
 | 
				
			||||||
                return fsFileRead(this->base_file.get(), offset, buffer, size, option.value, out);
 | 
					                return fsFileRead(std::addressof(this->base_file), offset, buffer, size, option.value, out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetSizeImpl(s64 *out) override final {
 | 
					            virtual Result GetSizeImpl(s64 *out) override final {
 | 
				
			||||||
                return fsFileGetSize(this->base_file.get(), out);
 | 
					                return fsFileGetSize(std::addressof(this->base_file), out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result FlushImpl() override final {
 | 
					            virtual Result FlushImpl() override final {
 | 
				
			||||||
                return fsFileFlush(this->base_file.get());
 | 
					                return fsFileFlush(std::addressof(this->base_file));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result WriteImpl(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
 | 
					            virtual Result WriteImpl(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
 | 
				
			||||||
                return fsFileWrite(this->base_file.get(), offset, buffer, size, option.value);
 | 
					                return fsFileWrite(std::addressof(this->base_file), offset, buffer, size, option.value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result SetSizeImpl(s64 size) override final {
 | 
					            virtual Result SetSizeImpl(s64 size) override final {
 | 
				
			||||||
                return fsFileSetSize(this->base_file.get(), size);
 | 
					                return fsFileSetSize(std::addressof(this->base_file), size);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OperateRangeImpl(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
 | 
					            virtual Result OperateRangeImpl(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final {
 | 
				
			||||||
                /* TODO: How should this be handled? */
 | 
					                R_UNLESS(op_id == OperationId::QueryRange,       fs::ResultUnsupportedOperationInFileServiceObjectAdapterA());
 | 
				
			||||||
                return fs::ResultNotImplemented();
 | 
					                R_UNLESS(dst_size == sizeof(FileQueryRangeInfo), fs::ResultInvalidSize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return fsFileOperateRange(std::addressof(this->base_file), static_cast<::FsOperationId>(op_id), offset, size, reinterpret_cast<::FsRangeInfo *>(dst));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
 | 
					            virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
 | 
				
			||||||
                return sf::cmif::DomainObjectId{serviceGetObjectId(&this->base_file->s)};
 | 
					                return sf::cmif::DomainObjectId{serviceGetObjectId(const_cast<::Service *>(std::addressof(this->base_file.s)))};
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class RemoteDirectory : public fsa::IDirectory {
 | 
					    class RemoteDirectory : public fsa::IDirectory, public impl::Newable {
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            std::unique_ptr<::FsDir> base_dir;
 | 
					            ::FsDir base_dir;
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            RemoteDirectory(::FsDir *d) : base_dir(d) { /* ... */ }
 | 
					            RemoteDirectory(const ::FsDir &d) : base_dir(d) { /* ... */ }
 | 
				
			||||||
            RemoteDirectory(std::unique_ptr<::FsDir> d) : base_dir(std::move(d)) { /* ... */ }
 | 
					 | 
				
			||||||
            RemoteDirectory(::FsDir d) {
 | 
					 | 
				
			||||||
                this->base_dir = std::make_unique<::FsDir>(d);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual ~RemoteDirectory() { fsDirClose(this->base_dir.get()); }
 | 
					            virtual ~RemoteDirectory() { fsDirClose(std::addressof(this->base_dir)); }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual Result ReadImpl(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) override final {
 | 
					            virtual Result ReadImpl(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) override final {
 | 
				
			||||||
                return fsDirRead(this->base_dir.get(), out_count, max_entries, out_entries);
 | 
					                return fsDirRead(std::addressof(this->base_dir), out_count, max_entries, out_entries);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetEntryCountImpl(s64 *out) override final {
 | 
					            virtual Result GetEntryCountImpl(s64 *out) override final {
 | 
				
			||||||
                return fsDirGetEntryCount(this->base_dir.get(), out);
 | 
					                return fsDirGetEntryCount(std::addressof(this->base_dir), out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
 | 
					            virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
 | 
				
			||||||
                return sf::cmif::DomainObjectId{serviceGetObjectId(&this->base_dir->s)};
 | 
					                return sf::cmif::DomainObjectId{serviceGetObjectId(const_cast<::Service *>(std::addressof(this->base_dir.s)))};
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class RemoteFileSystem : public fsa::IFileSystem {
 | 
					    class RemoteFileSystem : public fsa::IFileSystem, public impl::Newable {
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            std::unique_ptr<::FsFileSystem> base_fs;
 | 
					            ::FsFileSystem base_fs;
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            RemoteFileSystem(::FsFileSystem *fs) : base_fs(fs) { /* ... */ }
 | 
					            RemoteFileSystem(const ::FsFileSystem &fs) : base_fs(fs) { /* ... */ }
 | 
				
			||||||
            RemoteFileSystem(std::unique_ptr<::FsFileSystem> fs) : base_fs(std::move(fs)) { /* ... */ }
 | 
					 | 
				
			||||||
            RemoteFileSystem(::FsFileSystem fs) {
 | 
					 | 
				
			||||||
                this->base_fs = std::make_unique<::FsFileSystem>(fs);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual ~RemoteFileSystem() { fsFsClose(this->base_fs.get()); }
 | 
					            virtual ~RemoteFileSystem() { fsFsClose(std::addressof(this->base_fs)); }
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            Result GetPathForServiceObject(fssrv::sf::Path *out_path, const char *path) {
 | 
				
			||||||
 | 
					                /* Copy and null terminate. */
 | 
				
			||||||
 | 
					                std::strncpy(out_path->str, path, sizeof(out_path->str) - 1);
 | 
				
			||||||
 | 
					                out_path->str[sizeof(out_path->str) - 1] = '\x00';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Replace directory separators. */
 | 
				
			||||||
 | 
					                Replace(out_path->str, sizeof(out_path->str) - 1, StringTraits::AlternateDirectorySeparator, StringTraits::DirectorySeparator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Get lengths. */
 | 
				
			||||||
 | 
					                const auto mount_name_len = PathTool::IsWindowsAbsolutePath(path) ? 2 : 0;
 | 
				
			||||||
 | 
					                const auto rel_path = out_path->str + mount_name_len;
 | 
				
			||||||
 | 
					                const auto max_len  = fs::EntryNameLengthMax - mount_name_len;
 | 
				
			||||||
 | 
					                return VerifyPath(rel_path, max_len, max_len);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            virtual Result CreateFileImpl(const char *path, s64 size, int flags) override final {
 | 
					            virtual Result CreateFileImpl(const char *path, s64 size, int flags) override final {
 | 
				
			||||||
                return fsFsCreateFile(this->base_fs.get(), path, size, flags);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsCreateFile(std::addressof(this->base_fs), sf_path.str, size, flags);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result DeleteFileImpl(const char *path) override final {
 | 
					            virtual Result DeleteFileImpl(const char *path) override final {
 | 
				
			||||||
                return fsFsDeleteFile(this->base_fs.get(), path);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsDeleteFile(std::addressof(this->base_fs), sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result CreateDirectoryImpl(const char *path) override final {
 | 
					            virtual Result CreateDirectoryImpl(const char *path) override final {
 | 
				
			||||||
                return fsFsCreateDirectory(this->base_fs.get(), path);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsCreateDirectory(std::addressof(this->base_fs), sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result DeleteDirectoryImpl(const char *path) override final {
 | 
					            virtual Result DeleteDirectoryImpl(const char *path) override final {
 | 
				
			||||||
                return fsFsDeleteDirectory(this->base_fs.get(), path);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsDeleteDirectory(std::addressof(this->base_fs), sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result DeleteDirectoryRecursivelyImpl(const char *path) override final {
 | 
					            virtual Result DeleteDirectoryRecursivelyImpl(const char *path) override final {
 | 
				
			||||||
                return fsFsDeleteDirectoryRecursively(this->base_fs.get(), path);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsDeleteDirectoryRecursively(std::addressof(this->base_fs), sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result RenameFileImpl(const char *old_path, const char *new_path) override final {
 | 
					            virtual Result RenameFileImpl(const char *old_path, const char *new_path) override final {
 | 
				
			||||||
                return fsFsRenameFile(this->base_fs.get(), old_path, new_path);
 | 
					                fssrv::sf::Path old_sf_path;
 | 
				
			||||||
 | 
					                fssrv::sf::Path new_sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(new_sf_path), new_path));
 | 
				
			||||||
 | 
					                return fsFsRenameFile(std::addressof(this->base_fs), old_sf_path.str, new_sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result RenameDirectoryImpl(const char *old_path, const char *new_path) override final {
 | 
					            virtual Result RenameDirectoryImpl(const char *old_path, const char *new_path) override final {
 | 
				
			||||||
                return fsFsRenameDirectory(this->base_fs.get(), old_path, new_path);
 | 
					                fssrv::sf::Path old_sf_path;
 | 
				
			||||||
 | 
					                fssrv::sf::Path new_sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(new_sf_path), new_path));
 | 
				
			||||||
 | 
					                return fsFsRenameDirectory(std::addressof(this->base_fs), old_sf_path.str, new_sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetEntryTypeImpl(DirectoryEntryType *out, const char *path) override final {
 | 
					            virtual Result GetEntryTypeImpl(DirectoryEntryType *out, const char *path) override final {
 | 
				
			||||||
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                static_assert(sizeof(::FsDirEntryType) == sizeof(DirectoryEntryType));
 | 
					                static_assert(sizeof(::FsDirEntryType) == sizeof(DirectoryEntryType));
 | 
				
			||||||
                return fsFsGetEntryType(this->base_fs.get(), path, reinterpret_cast<::FsDirEntryType *>(out));
 | 
					                return fsFsGetEntryType(std::addressof(this->base_fs), sf_path.str, reinterpret_cast<::FsDirEntryType *>(out));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OpenFileImpl(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
 | 
					            virtual Result OpenFileImpl(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
 | 
				
			||||||
                FsFile f;
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
                R_TRY(fsFsOpenFile(this->base_fs.get(), path, mode, &f));
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                *out_file = std::make_unique<RemoteFile>(f);
 | 
					                FsFile f;
 | 
				
			||||||
 | 
					                R_TRY(fsFsOpenFile(std::addressof(this->base_fs), sf_path.str, mode, &f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto file = std::make_unique<RemoteFile>(f);
 | 
				
			||||||
 | 
					                R_UNLESS(file != nullptr, fs::ResultAllocationFailureInNew());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_file = std::move(file);
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result OpenDirectoryImpl(std::unique_ptr<fsa::IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) override final {
 | 
					            virtual Result OpenDirectoryImpl(std::unique_ptr<fsa::IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) override final {
 | 
				
			||||||
                FsDir d;
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
                R_TRY(fsFsOpenDirectory(this->base_fs.get(), path, mode, &d));
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                *out_dir = std::make_unique<RemoteDirectory>(d);
 | 
					                FsDir d;
 | 
				
			||||||
 | 
					                R_TRY(fsFsOpenDirectory(std::addressof(this->base_fs), sf_path.str, mode, &d));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto dir = std::make_unique<RemoteDirectory>(d);
 | 
				
			||||||
 | 
					                R_UNLESS(dir != nullptr, fs::ResultAllocationFailureInNew());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_dir = std::move(dir);
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result CommitImpl() override final {
 | 
					            virtual Result CommitImpl() override final {
 | 
				
			||||||
                return fsFsCommit(this->base_fs.get());
 | 
					                return fsFsCommit(std::addressof(this->base_fs));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetFreeSpaceSizeImpl(s64 *out, const char *path) {
 | 
					            virtual Result GetFreeSpaceSizeImpl(s64 *out, const char *path) {
 | 
				
			||||||
                return fsFsGetFreeSpace(this->base_fs.get(), path, out);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsGetFreeSpace(std::addressof(this->base_fs), sf_path.str, out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetTotalSpaceSizeImpl(s64 *out, const char *path) {
 | 
					            virtual Result GetTotalSpaceSizeImpl(s64 *out, const char *path) {
 | 
				
			||||||
                return fsFsGetTotalSpace(this->base_fs.get(), path, out);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsGetTotalSpace(std::addressof(this->base_fs), sf_path.str, out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result CleanDirectoryRecursivelyImpl(const char *path) {
 | 
					            virtual Result CleanDirectoryRecursivelyImpl(const char *path) {
 | 
				
			||||||
                return fsFsCleanDirectoryRecursively(this->base_fs.get(), path);
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsCleanDirectoryRecursively(std::addressof(this->base_fs), sf_path.str);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result GetFileTimeStampRawImpl(FileTimeStampRaw *out, const char *path) {
 | 
					            virtual Result GetFileTimeStampRawImpl(FileTimeStampRaw *out, const char *path) {
 | 
				
			||||||
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
                static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
 | 
					                static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
 | 
				
			||||||
                return fsFsGetFileTimeStampRaw(this->base_fs.get(), path, reinterpret_cast<::FsTimeStampRaw *>(out));
 | 
					                return fsFsGetFileTimeStampRaw(std::addressof(this->base_fs), sf_path.str, reinterpret_cast<::FsTimeStampRaw *>(out));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual Result QueryEntryImpl(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const char *path) {
 | 
					            virtual Result QueryEntryImpl(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const char *path) {
 | 
				
			||||||
                return fsFsQueryEntry(this->base_fs.get(), dst, dst_size, src, src_size, path, static_cast<FsFileSystemQueryId>(query));
 | 
					                fssrv::sf::Path sf_path;
 | 
				
			||||||
 | 
					                R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
 | 
				
			||||||
 | 
					                return fsFsQueryEntry(std::addressof(this->base_fs), dst, dst_size, src, src_size, sf_path.str, static_cast<FsFileSystemQueryId>(query));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,17 +16,17 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "fs_common.hpp"
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
#include "fs_istorage.hpp"
 | 
					#include "fs_istorage.hpp"
 | 
				
			||||||
 | 
					#include "impl/fs_newable.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fs {
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class RemoteStorage : public IStorage {
 | 
					    class RemoteStorage : public IStorage, public impl::Newable {
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            std::unique_ptr<::FsStorage> base_storage;
 | 
					            std::unique_ptr<::FsStorage, impl::Deleter> base_storage;
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            RemoteStorage(::FsStorage *s) : base_storage(s) { /* ... */ }
 | 
					            RemoteStorage(::FsStorage &s) {
 | 
				
			||||||
            RemoteStorage(std::unique_ptr<::FsStorage> s) : base_storage(std::move(s)) { /* ... */ }
 | 
					                this->base_storage = impl::MakeUnique<::FsStorage>();
 | 
				
			||||||
            RemoteStorage(::FsStorage s) {
 | 
					                *this->base_storage = s;
 | 
				
			||||||
                this->base_storage = std::make_unique<::FsStorage>(s);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual ~RemoteStorage() { fsStorageClose(this->base_storage.get()); }
 | 
					            virtual ~RemoteStorage() { fsStorageClose(this->base_storage.get()); }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										32
									
								
								libstratosphere/include/stratosphere/fs/fs_rights_id.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								libstratosphere/include/stratosphere/fs/fs_rights_id.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    union RightsId {
 | 
				
			||||||
 | 
					      u8 data[0x10];
 | 
				
			||||||
 | 
					      u64 data64[2];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(RightsId) == 0x10);
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<RightsId>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Rights ID API */
 | 
				
			||||||
 | 
					    Result GetRightsId(RightsId *out, const char *path);
 | 
				
			||||||
 | 
					    Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include "impl/fs_newable.hpp"
 | 
				
			||||||
 | 
					#include "fsa/fs_ifile.hpp"
 | 
				
			||||||
 | 
					#include "fsa/fs_idirectory.hpp"
 | 
				
			||||||
 | 
					#include "fsa/fs_ifilesystem.hpp"
 | 
				
			||||||
 | 
					#include "fs_dbm_hierarchical_rom_file_table.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class RomFsFileSystem : public fsa::IFileSystem, public impl::Newable {
 | 
				
			||||||
 | 
					        NON_COPYABLE(RomFsFileSystem);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            using RomFileTable = HierarchicalRomFileTable;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            RomFileTable rom_file_table;
 | 
				
			||||||
 | 
					            IStorage *base_storage;
 | 
				
			||||||
 | 
					            std::unique_ptr<IStorage> unique_storage;
 | 
				
			||||||
 | 
					            std::unique_ptr<IStorage> dir_bucket_storage;
 | 
				
			||||||
 | 
					            std::unique_ptr<IStorage> dir_entry_storage;
 | 
				
			||||||
 | 
					            std::unique_ptr<IStorage> file_bucket_storage;
 | 
				
			||||||
 | 
					            std::unique_ptr<IStorage> file_entry_storage;
 | 
				
			||||||
 | 
					            s64 entry_size;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            Result GetFileInfo(RomFileTable::FileInfo *out, const char *path);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            static Result GetRequiredWorkingMemorySize(size_t *out, IStorage *storage);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            RomFsFileSystem();
 | 
				
			||||||
 | 
					            virtual ~RomFsFileSystem() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Initialize(IStorage *base, void *work, size_t work_size, bool use_cache);
 | 
				
			||||||
 | 
					            Result Initialize(std::unique_ptr<IStorage>&& base, void *work, size_t work_size, bool use_cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IStorage *GetBaseStorage();
 | 
				
			||||||
 | 
					            RomFileTable *GetRomFileTable();
 | 
				
			||||||
 | 
					            Result GetFileBaseOffset(s64 *out, const char *path);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual Result CreateFileImpl(const char *path, s64 size, int flags) override;
 | 
				
			||||||
 | 
					            virtual Result DeleteFileImpl(const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result CreateDirectoryImpl(const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result DeleteDirectoryImpl(const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result DeleteDirectoryRecursivelyImpl(const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result RenameFileImpl(const char *old_path, const char *new_path) override;
 | 
				
			||||||
 | 
					            virtual Result RenameDirectoryImpl(const char *old_path, const char *new_path) override;
 | 
				
			||||||
 | 
					            virtual Result GetEntryTypeImpl(fs::DirectoryEntryType *out, const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result OpenFileImpl(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
 | 
				
			||||||
 | 
					            virtual Result OpenDirectoryImpl(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
 | 
				
			||||||
 | 
					            virtual Result CommitImpl() override;
 | 
				
			||||||
 | 
					            virtual Result GetFreeSpaceSizeImpl(s64 *out, const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result GetTotalSpaceSizeImpl(s64 *out, const char *path) override;
 | 
				
			||||||
 | 
					            virtual Result CleanDirectoryRecursivelyImpl(const char *path) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* These aren't accessible as commands. */
 | 
				
			||||||
 | 
					            virtual Result CommitProvisionallyImpl(s64 counter) override;
 | 
				
			||||||
 | 
					            virtual Result RollbackImpl() override;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include "fs_save_data_types.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result DeleteSaveData(SaveDataId id);
 | 
				
			||||||
 | 
					    Result DeleteSaveData(SaveDataSpaceId space_id, SaveDataId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetSaveDataFlags(u32 *out, SaveDataId id);
 | 
				
			||||||
 | 
					    Result GetSaveDataFlags(u32 *out, SaveDataSpaceId space_id, SaveDataId id);
 | 
				
			||||||
 | 
					    Result SetSaveDataFlags(SaveDataId id, SaveDataSpaceId space_id, u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include "fs_save_data_types.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result CommitSaveData(const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										159
									
								
								libstratosphere/include/stratosphere/fs/fs_save_data_types.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								libstratosphere/include/stratosphere/fs/fs_save_data_types.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using SaveDataId           = u64;
 | 
				
			||||||
 | 
					    using SystemSaveDataId     = u64;
 | 
				
			||||||
 | 
					    using SystemBcatSaveDataId = SystemSaveDataId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class SaveDataSpaceId : u8 {
 | 
				
			||||||
 | 
					        System       = 0,
 | 
				
			||||||
 | 
					        User         = 1,
 | 
				
			||||||
 | 
					        SdSystem     = 2,
 | 
				
			||||||
 | 
					        Temporary    = 3,
 | 
				
			||||||
 | 
					        SdUser       = 4,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ProperSystem = 100,
 | 
				
			||||||
 | 
					        SafeMode     = 101,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class SaveDataType : u8 {
 | 
				
			||||||
 | 
					        System     = 0,
 | 
				
			||||||
 | 
					        Account    = 1,
 | 
				
			||||||
 | 
					        Bcat       = 2,
 | 
				
			||||||
 | 
					        Device     = 3,
 | 
				
			||||||
 | 
					        Temporary  = 4,
 | 
				
			||||||
 | 
					        Cache      = 5,
 | 
				
			||||||
 | 
					        SystemBcat = 6,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class SaveDataRank : u8 {
 | 
				
			||||||
 | 
					        Primary   = 0,
 | 
				
			||||||
 | 
					        Secondary = 1,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct UserId {
 | 
				
			||||||
 | 
					        u64 data[2];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<UserId>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator<(const UserId &lhs, const UserId &rhs) {
 | 
				
			||||||
 | 
					        if (lhs.data[0] < rhs.data[0]) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } else if (lhs.data[0] == rhs.data[0] && lhs.data[1] < rhs.data[1]) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator==(const UserId &lhs, const UserId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.data[0] == rhs.data[0] && lhs.data[1] == rhs.data[1];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator!=(const UserId &lhs, const UserId &rhs) {
 | 
				
			||||||
 | 
					        return !(lhs == rhs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline SystemSaveDataId InvalidSystemSaveDataId = 0;
 | 
				
			||||||
 | 
					    constexpr inline UserId InvalidUserId = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum SaveDataFlags : u32 {
 | 
				
			||||||
 | 
					        SaveDataFlags_None                                                = (0 << 0),
 | 
				
			||||||
 | 
					        SaveDataFlags_KeepAfterResettingSystemSaveData                    = (1 << 0),
 | 
				
			||||||
 | 
					        SaveDataFlags_KeepAfterRefurbishment                              = (1 << 1),
 | 
				
			||||||
 | 
					        SaveDataFlags_KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
 | 
				
			||||||
 | 
					        SaveDataFlags_NeedsSecureDelete                                   = (1 << 3),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SaveDataCreationInfo {
 | 
				
			||||||
 | 
					        s64 size;
 | 
				
			||||||
 | 
					        s64 journal_size;
 | 
				
			||||||
 | 
					        s64 block_size;
 | 
				
			||||||
 | 
					        u64 owner_id;
 | 
				
			||||||
 | 
					        u32 flags;
 | 
				
			||||||
 | 
					        SaveDataSpaceId space_id;
 | 
				
			||||||
 | 
					        bool pseudo;
 | 
				
			||||||
 | 
					        u8 reserved[0x1A];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<SaveDataCreationInfo>::value);
 | 
				
			||||||
 | 
					    static_assert(sizeof(SaveDataCreationInfo) == 0x40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SaveDataAttribute {
 | 
				
			||||||
 | 
					        ncm::ProgramId program_id;
 | 
				
			||||||
 | 
					        UserId user_id;
 | 
				
			||||||
 | 
					        SystemSaveDataId system_save_data_id;
 | 
				
			||||||
 | 
					        SaveDataType type;
 | 
				
			||||||
 | 
					        SaveDataRank rank;
 | 
				
			||||||
 | 
					        u16 index;
 | 
				
			||||||
 | 
					        u8 reserved[0x1C];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id, u16 index, SaveDataRank rank) {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                .program_id          = program_id,
 | 
				
			||||||
 | 
					                .user_id             = user_id,
 | 
				
			||||||
 | 
					                .system_save_data_id = system_save_data_id,
 | 
				
			||||||
 | 
					                .type                = type,
 | 
				
			||||||
 | 
					                .rank                = rank,
 | 
				
			||||||
 | 
					                .index               = index,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id, u16 index) {
 | 
				
			||||||
 | 
					            return Make(program_id, type, user_id, system_save_data_id, index, SaveDataRank::Primary);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr SaveDataAttribute Make(ncm::ProgramId program_id, SaveDataType type, UserId user_id, SystemSaveDataId system_save_data_id) {
 | 
				
			||||||
 | 
					            return Make(program_id, type, user_id, system_save_data_id, 0, SaveDataRank::Primary);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(SaveDataAttribute) == 0x40);
 | 
				
			||||||
 | 
					    static_assert(std::is_trivially_destructible<SaveDataAttribute>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator<(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
 | 
				
			||||||
 | 
					        return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.index, lhs.rank) <
 | 
				
			||||||
 | 
					               std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.index, rhs.rank);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator==(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
 | 
				
			||||||
 | 
					        return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.type, lhs.rank, lhs.index) ==
 | 
				
			||||||
 | 
					               std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.type, rhs.rank, rhs.index);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline bool operator!=(const SaveDataAttribute &lhs, const SaveDataAttribute &rhs) {
 | 
				
			||||||
 | 
					        return !(lhs == rhs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline size_t DefaultSaveDataBlockSize = 16_KB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SaveDataExtraData {
 | 
				
			||||||
 | 
					        SaveDataAttribute attr;
 | 
				
			||||||
 | 
					        u64 owner_id;
 | 
				
			||||||
 | 
					        s64 timestamp;
 | 
				
			||||||
 | 
					        u32 flags;
 | 
				
			||||||
 | 
					        u8 pad[4];
 | 
				
			||||||
 | 
					        s64 available_size;
 | 
				
			||||||
 | 
					        s64 journal_size;
 | 
				
			||||||
 | 
					        s64 commit_id;
 | 
				
			||||||
 | 
					        u8 unused[0x190];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(SaveDataExtraData) == 0x200);
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<SaveDataExtraData>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								libstratosphere/include/stratosphere/fs/fs_sd_card.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libstratosphere/include/stratosphere/fs/fs_sd_card.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountSdCard(const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool IsSignedSystemPartitionOnSdCardValid(const char *system_root_path);
 | 
				
			||||||
 | 
					    bool IsSignedSystemPartitionOnSdCardValidDeprecated();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										144
									
								
								libstratosphere/include/stratosphere/fs/fs_substorage.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								libstratosphere/include/stratosphere/fs/fs_substorage.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "impl/fs_newable.hpp"
 | 
				
			||||||
 | 
					#include "fs_istorage.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class SubStorage : public ::ams::fs::IStorage, public ::ams::fs::impl::Newable {
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<IStorage> shared_base_storage;
 | 
				
			||||||
 | 
					            fs::IStorage *base_storage;
 | 
				
			||||||
 | 
					            s64 offset;
 | 
				
			||||||
 | 
					            s64 size;
 | 
				
			||||||
 | 
					            bool resizable;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            constexpr bool IsValid() const {
 | 
				
			||||||
 | 
					                return this->base_storage != nullptr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            SubStorage() : shared_base_storage(), base_storage(nullptr), offset(0), size(0), resizable(false) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SubStorage(const SubStorage &rhs) : shared_base_storage(), base_storage(rhs.base_storage), offset(rhs.offset), size(rhs.size),  resizable(rhs.resizable) { /* ... */}
 | 
				
			||||||
 | 
					            SubStorage &operator=(const SubStorage &rhs) {
 | 
				
			||||||
 | 
					                if (this != std::addressof(rhs)) {
 | 
				
			||||||
 | 
					                    this->base_storage        = rhs.base_storage;
 | 
				
			||||||
 | 
					                    this->offset              = rhs.offset;
 | 
				
			||||||
 | 
					                    this->size                = rhs.size;
 | 
				
			||||||
 | 
					                    this->resizable           = rhs.resizable;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SubStorage(IStorage *storage, s64 o, s64 sz) : shared_base_storage(), base_storage(storage), offset(o), size(sz) {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->IsValid());
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->offset  >= 0);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->size    >= 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SubStorage(std::shared_ptr<IStorage> storage, s64 o, s64 sz) : shared_base_storage(storage), base_storage(storage.get()), offset(o), size(sz) {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->IsValid());
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->offset  >= 0);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->size    >= 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SubStorage(SubStorage *sub, s64 o, s64 sz) : shared_base_storage(), base_storage(sub->base_storage), offset(o + sub->offset), size(sz) {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->IsValid());
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->offset  >= 0);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->size    >= 0);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(sub->size     >= o + sz);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            void SetResizable(bool rsz) {
 | 
				
			||||||
 | 
					                this->resizable = rsz;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual Result Read(s64 offset, void *buffer, size_t size) override {
 | 
				
			||||||
 | 
					                /* Ensure we're initialized. */
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(),                                  fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Succeed immediately on zero-sized operation. */
 | 
				
			||||||
 | 
					                R_SUCCEED_IF(size == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Validate arguments and read. */
 | 
				
			||||||
 | 
					                R_UNLESS(buffer != nullptr,                                fs::ResultNullptrArgument());
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsRangeValid(offset, size, this->size), fs::ResultOutOfRange());
 | 
				
			||||||
 | 
					                return this->base_storage->Read(this->offset + offset, buffer, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result Write(s64 offset, const void *buffer, size_t size) override{
 | 
				
			||||||
 | 
					                /* Ensure we're initialized. */
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(),                                  fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Succeed immediately on zero-sized operation. */
 | 
				
			||||||
 | 
					                R_SUCCEED_IF(size == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Validate arguments and write. */
 | 
				
			||||||
 | 
					                R_UNLESS(buffer != nullptr,                                fs::ResultNullptrArgument());
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsRangeValid(offset, size, this->size), fs::ResultOutOfRange());
 | 
				
			||||||
 | 
					                return this->base_storage->Write(this->offset + offset, buffer, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result Flush() override {
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					                return this->base_storage->Flush();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result SetSize(s64 size) override {
 | 
				
			||||||
 | 
					                /* Ensure we're initialized and validate arguments. */
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(),                                    fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					                R_UNLESS(this->resizable,                                    fs::ResultUnsupportedOperationInSubStorageA());
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsOffsetAndSizeValid(this->offset, size), fs::ResultInvalidSize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Ensure that we're allowed to set size. */
 | 
				
			||||||
 | 
					                s64 cur_size;
 | 
				
			||||||
 | 
					                R_TRY(this->base_storage->GetSize(std::addressof(cur_size)));
 | 
				
			||||||
 | 
					                R_UNLESS(cur_size == this->offset + this->size, fs::ResultUnsupportedOperationInSubStorageB());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Set the size. */
 | 
				
			||||||
 | 
					                R_TRY(this->base_storage->SetSize(this->offset + size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this->size = size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result GetSize(s64 *out) override {
 | 
				
			||||||
 | 
					                /* Ensure we're initialized. */
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(), fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out = this->size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
 | 
				
			||||||
 | 
					                /* Ensure we're initialized. */
 | 
				
			||||||
 | 
					                R_UNLESS(this->IsValid(),                              fs::ResultNotInitialized());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Succeed immediately on zero-sized operation. */
 | 
				
			||||||
 | 
					                R_SUCCEED_IF(size == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Validate arguments and operate. */
 | 
				
			||||||
 | 
					                R_UNLESS(IStorage::IsOffsetAndSizeValid(offset, size), fs::ResultOutOfRange());
 | 
				
			||||||
 | 
					                return this->base_storage->OperateRange(dst, dst_size, op_id, this->offset + offset, size, src, src_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using IStorage::OperateRange;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								libstratosphere/include/stratosphere/fs/fs_system_data.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libstratosphere/include/stratosphere/fs/fs_system_data.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result QueryMountSystemDataCacheSize(size_t *out, ncm::SystemDataId data_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountSystemData(const char *name, ncm::SystemDataId data_id);
 | 
				
			||||||
 | 
					    Result MountSystemData(const char *name, ncm::SystemDataId data_id, void *cache_buffer, size_t cache_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "fs_common.hpp"
 | 
				
			||||||
 | 
					#include "fs_save_data_types.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void DisableAutoSaveDataCreation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SystemSaveDataId save_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					    Result CreateSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId save_id, UserId user_id, u64 owner_id, s64 size, s64 journal_size, u32 flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountSystemSaveData(const char *name, SystemSaveDataId id);
 | 
				
			||||||
 | 
					    Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountSystemSaveData(const char *name, SystemSaveDataId id, UserId user_id);
 | 
				
			||||||
 | 
					    Result MountSystemSaveData(const char *name, SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result DeleteSystemSaveData(SaveDataSpaceId space_id, SystemSaveDataId id, UserId user_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -96,10 +96,12 @@ namespace ams::fs::fsa {
 | 
				
			|||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Result DrySetSize(s64 size, OpenMode open_mode) {
 | 
					            Result DrySetSize(s64 size, fs::OpenMode open_mode) {
 | 
				
			||||||
                /* Check that we can write. */
 | 
					                /* Check that we can write. */
 | 
				
			||||||
                R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultInvalidOperationForOpenMode());
 | 
					                R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultInvalidOperationForOpenMode());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                AMS_ASSERT(size >= 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,8 @@ namespace ams::fs::fsa {
 | 
				
			|||||||
    class IDirectory;
 | 
					    class IDirectory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enum class QueryId {
 | 
					    enum class QueryId {
 | 
				
			||||||
        SetConcatenationFileAttribute = FsFileSystemQueryId_SetConcatenationFileAttribute
 | 
					        SetConcatenationFileAttribute        = 0,
 | 
				
			||||||
 | 
					        IsSignedSystemPartitionOnSdCardValid = 2,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class IFileSystem {
 | 
					    class IFileSystem {
 | 
				
			||||||
@ -88,10 +89,10 @@ namespace ams::fs::fsa {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) {
 | 
					            Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) {
 | 
				
			||||||
                R_UNLESS(path != nullptr,                      fs::ResultInvalidPath());
 | 
					                R_UNLESS(path != nullptr,                                                               fs::ResultInvalidPath());
 | 
				
			||||||
                R_UNLESS(out_dir != nullptr,                   fs::ResultNullptrArgument());
 | 
					                R_UNLESS(out_dir != nullptr,                                                            fs::ResultNullptrArgument());
 | 
				
			||||||
                R_UNLESS((mode &  OpenDirectoryMode_All) != 0, fs::ResultInvalidArgument());
 | 
					                R_UNLESS((mode &  OpenDirectoryMode_All) != 0,                                          fs::ResultInvalidArgument());
 | 
				
			||||||
                R_UNLESS((mode & ~OpenDirectoryMode_All) == 0, fs::ResultInvalidArgument());
 | 
					                R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidArgument());
 | 
				
			||||||
                return this->OpenDirectoryImpl(out_dir, path, mode);
 | 
					                return this->OpenDirectoryImpl(out_dir, path, mode);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								libstratosphere/include/stratosphere/fs/fsa/fs_registrar.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								libstratosphere/include/stratosphere/fs/fsa/fs_registrar.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "../fs_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs::fsa {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ICommonMountNameGenerator {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual ~ICommonMountNameGenerator() { /* ... */ }
 | 
				
			||||||
 | 
					            virtual Result GenerateCommonMountName(char *name, size_t name_size) = 0;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IFileSystem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs);
 | 
				
			||||||
 | 
					    Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs, std::unique_ptr<ICommonMountNameGenerator> &&generator);
 | 
				
			||||||
 | 
					    Result Register(const char *name, std::unique_ptr<IFileSystem> &&fs, std::unique_ptr<ICommonMountNameGenerator> &&generator, bool use_data_cache, bool use_path_cache, bool multi_commit_supported);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Unregister(const char *name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Delimiting of mount names. */
 | 
				
			||||||
 | 
					    constexpr inline const char ReservedMountNamePrefixCharacter                = '@';
 | 
				
			||||||
 | 
					    constexpr inline const char * const MountNameDelimiter                      = ":/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Filesystem names. */
 | 
				
			||||||
 | 
					    constexpr inline const char * const HostRootFileSystemMountName             = "@Host";
 | 
				
			||||||
 | 
					    constexpr inline const char * const SdCardFileSystemMountName               = "@Sdcard";
 | 
				
			||||||
 | 
					    constexpr inline const char * const GameCardFileSystemMountName             = "@Gc";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline size_t GameCardFileSystemMountNameSuffixLength             = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline const char * const GameCardFileSystemMountNameUpdateSuffix = "U";
 | 
				
			||||||
 | 
					    constexpr inline const char * const GameCardFileSystemMountNameNormalSuffix = "N";
 | 
				
			||||||
 | 
					    constexpr inline const char * const GameCardFileSystemMountNameSecureSuffix = "S";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Built-in storage names. */
 | 
				
			||||||
 | 
					    constexpr inline const char * const BisCalibrationFilePartitionMountName    = "@CalibFile";
 | 
				
			||||||
 | 
					    constexpr inline const char * const BisSafeModePartitionMountName           = "@Safe";
 | 
				
			||||||
 | 
					    constexpr inline const char * const BisUserPartitionMountName               = "@User";
 | 
				
			||||||
 | 
					    constexpr inline const char * const BisSystemPartitionMountName             = "@System";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Content storage names. */
 | 
				
			||||||
 | 
					    constexpr inline const char * const ContentStorageSystemMountName           = "@SystemContent";
 | 
				
			||||||
 | 
					    constexpr inline const char * const ContentStorageUserMountName             = "@UserContent";
 | 
				
			||||||
 | 
					    constexpr inline const char * const ContentStorageSdCardMountName           = "@SdCardContent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Registered update partition. */
 | 
				
			||||||
 | 
					    constexpr inline const char * const RegisteredUpdatePartitionMountName      = "@RegUpdate";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								libstratosphere/include/stratosphere/fs/impl/fs_data.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								libstratosphere/include/stratosphere/fs/impl/fs_data.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_common.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result QueryMountDataCacheSize(size_t *out, ncm::DataId data_id, ncm::StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id);
 | 
				
			||||||
 | 
					    Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id, void *cache_buffer, size_t cache_size);
 | 
				
			||||||
 | 
					    Result MountData(const char *name, ncm::DataId data_id, ncm::StorageId storage_id, void *cache_buffer, size_t cache_size, bool use_data_cache, bool use_path_cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum FileSystemProxyType {
 | 
				
			||||||
 | 
					        FileSystemProxyType_Code            = 0,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Rom             = 1,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Logo            = 2,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Control         = 3,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Manual          = 4,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Meta            = 5,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Data            = 6,
 | 
				
			||||||
 | 
					        FileSystemProxyType_Package         = 7,
 | 
				
			||||||
 | 
					        FileSystemProxyType_UpdatePartition = 8,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								libstratosphere/include/stratosphere/fs/impl/fs_newable.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libstratosphere/include/stratosphere/fs/impl/fs_newable.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_memory_management.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::fs::impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Newable {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            static void *operator new(size_t size) {
 | 
				
			||||||
 | 
					                return ::ams::fs::impl::Allocate(size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static void *operator new[](size_t size) {
 | 
				
			||||||
 | 
					                return ::ams::fs::impl::Allocate(size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static void operator delete(void *ptr, size_t size) {
 | 
				
			||||||
 | 
					                return ::ams::fs::impl::Deallocate(ptr, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static void operator delete[](void *ptr, size_t size) {
 | 
				
			||||||
 | 
					                return ::ams::fs::impl::Deallocate(ptr, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -14,9 +14,9 @@
 | 
				
			|||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "../fs/fs_common.hpp"
 | 
					#include <stratosphere/fs/fs_common.hpp>
 | 
				
			||||||
#include "../fs/fs_directory.hpp"
 | 
					#include <stratosphere/fs/fs_directory.hpp>
 | 
				
			||||||
#include "../sf/sf_buffer_tags.hpp"
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::fssrv::sf {
 | 
					namespace ams::fssrv::sf {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,9 +13,8 @@
 | 
				
			|||||||
 * You should have received a copy of the GNU General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "kvdb_auto_buffer.hpp"
 | 
					#include <stratosphere/kvdb/kvdb_auto_buffer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::kvdb {
 | 
					namespace ams::kvdb {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@
 | 
				
			|||||||
 * You should have received a copy of the GNU General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vapours.hpp>
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,7 +38,7 @@ namespace ams::kvdb {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            AutoBuffer& operator=(AutoBuffer &&rhs) {
 | 
					            AutoBuffer& operator=(AutoBuffer &&rhs) {
 | 
				
			||||||
                rhs.Swap(*this);
 | 
					                AutoBuffer(std::move(rhs)).Swap(*this);
 | 
				
			||||||
                return *this;
 | 
					                return *this;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,9 +69,8 @@ namespace ams::kvdb {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                /* Allocate a buffer. */
 | 
					                /* Allocate a buffer. */
 | 
				
			||||||
                this->buffer = static_cast<u8 *>(std::malloc(size));
 | 
					                this->buffer = static_cast<u8 *>(std::malloc(size));
 | 
				
			||||||
                if (this->buffer == nullptr) {
 | 
					                R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
 | 
				
			||||||
                    return ResultAllocationFailed();
 | 
					
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                this->size = size;
 | 
					                this->size = size;
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@
 | 
				
			|||||||
 * You should have received a copy of the GNU General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vapours.hpp>
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,6 +50,7 @@ namespace ams::kvdb {
 | 
				
			|||||||
                std::va_list args;
 | 
					                std::va_list args;
 | 
				
			||||||
                va_start(args, format);
 | 
					                va_start(args, format);
 | 
				
			||||||
                CheckLength(std::vsnprintf(string.buffer, N, format, args));
 | 
					                CheckLength(std::vsnprintf(string.buffer, N, format, args));
 | 
				
			||||||
 | 
					                string.buffer[N - 1] = 0;
 | 
				
			||||||
                va_end(args);
 | 
					                va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return string;
 | 
					                return string;
 | 
				
			||||||
@ -74,6 +74,7 @@ namespace ams::kvdb {
 | 
				
			|||||||
                /* Ensure string can fit in our buffer. */
 | 
					                /* Ensure string can fit in our buffer. */
 | 
				
			||||||
                CheckLength(strnlen(s, N));
 | 
					                CheckLength(strnlen(s, N));
 | 
				
			||||||
                std::strncpy(this->buffer, s, N);
 | 
					                std::strncpy(this->buffer, s, N);
 | 
				
			||||||
 | 
					                this->buffer[N - 1] = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void SetFormat(const char *format, ...) __attribute__((format (printf, 2, 3))) {
 | 
					            void SetFormat(const char *format, ...) __attribute__((format (printf, 2, 3))) {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,9 +13,10 @@
 | 
				
			|||||||
 * You should have received a copy of the GNU General Public License
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <stratosphere/fs/fs_filesystem.hpp>
 | 
				
			||||||
#include "kvdb_bounded_string.hpp"
 | 
					#include <stratosphere/fs/fs_file.hpp>
 | 
				
			||||||
#include "kvdb_file_key_value_store.hpp"
 | 
					#include <stratosphere/kvdb/kvdb_bounded_string.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/kvdb/kvdb_file_key_value_store.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::kvdb {
 | 
					namespace ams::kvdb {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,16 +40,16 @@ namespace ams::kvdb {
 | 
				
			|||||||
            public:
 | 
					            public:
 | 
				
			||||||
                static Result CreateNewList(const char *path) {
 | 
					                static Result CreateNewList(const char *path) {
 | 
				
			||||||
                    /* Create new lru_list.dat. */
 | 
					                    /* Create new lru_list.dat. */
 | 
				
			||||||
                    R_TRY(fsdevCreateFile(path, FileSize, 0));
 | 
					                    R_TRY(fs::CreateFile(path, FileSize));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Open the file. */
 | 
					                    /* Open the file. */
 | 
				
			||||||
                    FILE *fp = fopen(path, "r+b");
 | 
					                    fs::FileHandle file;
 | 
				
			||||||
                    R_UNLESS(fp != nullptr, fsdevGetLastResult());
 | 
					                    R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write));
 | 
				
			||||||
                    ON_SCOPE_EXIT { fclose(fp); };
 | 
					                    ON_SCOPE_EXIT { fs::CloseFile(file); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Write new header with zero entries to the file. */
 | 
					                    /* Write new header with zero entries to the file. */
 | 
				
			||||||
                    LruHeader new_header = { .entry_count = 0, };
 | 
					                    LruHeader new_header = { .entry_count = 0, };
 | 
				
			||||||
                    R_UNLESS(fwrite(&new_header, sizeof(new_header), 1, fp) == 1, fsdevGetLastResult());
 | 
					                    R_TRY(fs::WriteFile(file, 0, std::addressof(new_header), sizeof(new_header), fs::WriteOption::Flush));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return ResultSuccess();
 | 
					                    return ResultSuccess();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -80,36 +81,33 @@ namespace ams::kvdb {
 | 
				
			|||||||
                    std::memset(this->keys, 0, BufferSize);
 | 
					                    std::memset(this->keys, 0, BufferSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Open file. */
 | 
					                    /* Open file. */
 | 
				
			||||||
                    FILE *fp = fopen(this->file_path, "rb");
 | 
					                    fs::FileHandle file;
 | 
				
			||||||
                    R_UNLESS(fp != nullptr, fsdevGetLastResult());
 | 
					                    R_TRY(fs::OpenFile(std::addressof(file), this->file_path, fs::OpenMode_Read));
 | 
				
			||||||
                    ON_SCOPE_EXIT { fclose(fp); };
 | 
					                    ON_SCOPE_EXIT { fs::CloseFile(file); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Read header. */
 | 
					                    /* Read header. */
 | 
				
			||||||
                    R_UNLESS(fread(&this->header, sizeof(this->header), 1, fp) == 1, fsdevGetLastResult());
 | 
					                    R_TRY(fs::ReadFile(file, 0, std::addressof(this->header), sizeof(this->header)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Read entries. */
 | 
					                    /* Read entries. */
 | 
				
			||||||
                    const size_t count = this->GetCount();
 | 
					                    R_TRY(fs::ReadFile(file, sizeof(this->header), this->keys, BufferSize));
 | 
				
			||||||
                    if (count > 0) {
 | 
					 | 
				
			||||||
                        R_UNLESS(fread(this->keys, std::min(BufferSize, sizeof(Key) * count), 1, fp) == 1, fsdevGetLastResult());
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return ResultSuccess();
 | 
					                    return ResultSuccess();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Result Save() {
 | 
					                Result Save() {
 | 
				
			||||||
                    /* Open file. */
 | 
					                    /* Open file. */
 | 
				
			||||||
                    FILE *fp = fopen(this->file_path, "r+b");
 | 
					                    fs::FileHandle file;
 | 
				
			||||||
                    R_UNLESS(fp != nullptr, fsdevGetLastResult());
 | 
					                    R_TRY(fs::OpenFile(std::addressof(file), this->file_path, fs::OpenMode_Read));
 | 
				
			||||||
                    ON_SCOPE_EXIT { fclose(fp); };
 | 
					                    ON_SCOPE_EXIT { fs::CloseFile(file); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Write header. */
 | 
					                    /* Write header. */
 | 
				
			||||||
                    R_UNLESS(fwrite(&this->header, sizeof(this->header), 1, fp) == 1, fsdevGetLastResult());
 | 
					                    R_TRY(fs::WriteFile(file, 0, std::addressof(this->header), sizeof(this->header), fs::WriteOption::None));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Write entries. */
 | 
					                    /* Write entries. */
 | 
				
			||||||
                    R_UNLESS(fwrite(this->keys, BufferSize, 1, fp) == 1, fsdevGetLastResult());
 | 
					                    R_TRY(fs::WriteFile(file, sizeof(this->header), this->keys, BufferSize, fs::WriteOption::None));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Flush. */
 | 
					                    /* Flush. */
 | 
				
			||||||
                    fflush(fp);
 | 
					                    R_TRY(fs::FlushFile(file));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return ResultSuccess();
 | 
					                    return ResultSuccess();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -209,44 +207,37 @@ namespace ams::kvdb {
 | 
				
			|||||||
                return Path::MakeFormat("%s/%s", dir, "kvs");
 | 
					                return Path::MakeFormat("%s/%s", dir, "kvs");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static Result Exists(bool *out, const char *path, bool is_dir) {
 | 
					            static Result Exists(bool *out, const char *path, fs::DirectoryEntryType type) {
 | 
				
			||||||
                /* Set out to false initially. */
 | 
					                /* Set out to false initially. */
 | 
				
			||||||
                *out = false;
 | 
					                *out = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Check that the path exists, and that our entry type is correct. */
 | 
					                /* Try to get the entry type. */
 | 
				
			||||||
                {
 | 
					                fs::DirectoryEntryType entry_type;
 | 
				
			||||||
                    struct stat st;
 | 
					                R_TRY_CATCH(fs::GetEntryType(std::addressof(entry_type), path)) {
 | 
				
			||||||
 | 
					                    /* If the path doesn't exist, nothing has gone wrong. */
 | 
				
			||||||
 | 
					                    R_CONVERT(fs::ResultPathNotFound, ResultSuccess());
 | 
				
			||||||
 | 
					                } R_END_TRY_CATCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (stat(path, &st) != 0) {
 | 
					                /* Check that the entry type is correct. */
 | 
				
			||||||
                        R_TRY_CATCH(fsdevGetLastResult()) {
 | 
					                R_UNLESS(entry_type == type, ResultInvalidFilesystemState());
 | 
				
			||||||
                            /* If the path doesn't exist, nothing has gone wrong. */
 | 
					 | 
				
			||||||
                            R_CONVERT(fs::ResultPathNotFound, ResultSuccess());
 | 
					 | 
				
			||||||
                        } R_END_TRY_CATCH;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (is_dir) {
 | 
					 | 
				
			||||||
                        R_UNLESS((S_ISDIR(st.st_mode)), ResultInvalidFilesystemState());
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        R_UNLESS((S_ISREG(st.st_mode)), ResultInvalidFilesystemState());
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* The entry exists and is the correct type. */
 | 
				
			||||||
                *out = true;
 | 
					                *out = true;
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static Result DirectoryExists(bool *out, const char *path) {
 | 
					            static Result DirectoryExists(bool *out, const char *path) {
 | 
				
			||||||
                return Exists(out, path, true);
 | 
					                return Exists(out, path, fs::DirectoryEntryType_Directory);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            static Result FileExists(bool *out, const char *path) {
 | 
					            static Result FileExists(bool *out, const char *path) {
 | 
				
			||||||
                return Exists(out, path, false);
 | 
					                return Exists(out, path, fs::DirectoryEntryType_File);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            static Result CreateNewCache(const char *dir) {
 | 
					            static Result CreateNewCache(const char *dir) {
 | 
				
			||||||
                /* Make a new key value store filesystem, and a new lru_list.dat. */
 | 
					                /* Make a new key value store filesystem, and a new lru_list.dat. */
 | 
				
			||||||
                R_TRY(LeastRecentlyUsedList::CreateNewList(GetLeastRecentlyUsedListPath(dir)));
 | 
					                R_TRY(LeastRecentlyUsedList::CreateNewList(GetLeastRecentlyUsedListPath(dir)));
 | 
				
			||||||
                R_UNLESS(mkdir(GetFileKeyValueStorePath(dir), 0) == 0, fsdevGetLastResult());
 | 
					                R_TRY(fs::CreateDirectory(dir));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,8 @@
 | 
				
			|||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "../os.hpp"
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
#include "kvdb_bounded_string.hpp"
 | 
					#include <stratosphere/kvdb/kvdb_bounded_string.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::kvdb {
 | 
					namespace ams::kvdb {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,10 +15,11 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <stratosphere/fs/fs_filesystem.hpp>
 | 
				
			||||||
#include "kvdb_auto_buffer.hpp"
 | 
					#include <stratosphere/fs/fs_file.hpp>
 | 
				
			||||||
#include "kvdb_archive.hpp"
 | 
					#include <stratosphere/kvdb/kvdb_auto_buffer.hpp>
 | 
				
			||||||
#include "kvdb_bounded_string.hpp"
 | 
					#include <stratosphere/kvdb/kvdb_archive.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/kvdb/kvdb_bounded_string.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::kvdb {
 | 
					namespace ams::kvdb {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -262,11 +263,9 @@ namespace ams::kvdb {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            Result Initialize(const char *dir, size_t capacity) {
 | 
					            Result Initialize(const char *dir, size_t capacity) {
 | 
				
			||||||
                /* Ensure that the passed path is a directory. */
 | 
					                /* Ensure that the passed path is a directory. */
 | 
				
			||||||
                {
 | 
					                fs::DirectoryEntryType entry_type;
 | 
				
			||||||
                    struct stat st;
 | 
					                R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
 | 
				
			||||||
                    R_UNLESS(stat(dir, &st) == 0,   fs::ResultPathNotFound());
 | 
					                R_UNLESS(entry_type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound());
 | 
				
			||||||
                    R_UNLESS((S_ISDIR(st.st_mode)), fs::ResultPathNotFound());
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Set paths. */
 | 
					                /* Set paths. */
 | 
				
			||||||
                this->path.SetFormat("%s%s", dir, "/imkvdb.arc");
 | 
					                this->path.SetFormat("%s%s", dir, "/imkvdb.arc");
 | 
				
			||||||
@ -337,7 +336,7 @@ namespace ams::kvdb {
 | 
				
			|||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Result Save() {
 | 
					            Result Save(bool destructive = false) {
 | 
				
			||||||
                /* Create a buffer to hold the archive. */
 | 
					                /* Create a buffer to hold the archive. */
 | 
				
			||||||
                AutoBuffer buffer;
 | 
					                AutoBuffer buffer;
 | 
				
			||||||
                R_TRY(buffer.Initialize(this->GetArchiveSize()));
 | 
					                R_TRY(buffer.Initialize(this->GetArchiveSize()));
 | 
				
			||||||
@ -353,7 +352,7 @@ namespace ams::kvdb {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Save the buffer to disk. */
 | 
					                /* Save the buffer to disk. */
 | 
				
			||||||
                return this->Commit(buffer);
 | 
					                return this->Commit(buffer, destructive);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Result Set(const Key &key, const void *value, size_t value_size) {
 | 
					            Result Set(const Key &key, const void *value, size_t value_size) {
 | 
				
			||||||
@ -468,27 +467,38 @@ namespace ams::kvdb {
 | 
				
			|||||||
                return this->index.find(key);
 | 
					                return this->index.find(key);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            Result Commit(const AutoBuffer &buffer) {
 | 
					            Result SaveArchiveToFile(const char *path, const void *buf, size_t size) {
 | 
				
			||||||
                /* Try to delete temporary archive, but allow deletion failure (it may not exist). */
 | 
					                /* Try to delete the archive, but allow deletion failure. */
 | 
				
			||||||
                std::remove(this->temp_path.Get());
 | 
					                fs::DeleteFile(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Create new temporary archive. */
 | 
					                /* Create new archive. */
 | 
				
			||||||
                R_TRY(fsdevCreateFile(this->temp_path.Get(), buffer.GetSize(), 0));
 | 
					                R_TRY(fs::CreateFile(path, size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Write data to the temporary archive. */
 | 
					                /* Write data to the archive. */
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    FILE *f = fopen(this->temp_path, "r+b");
 | 
					                    fs::FileHandle file;
 | 
				
			||||||
                    R_UNLESS(f != nullptr, fsdevGetLastResult());
 | 
					                    R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write));
 | 
				
			||||||
                    ON_SCOPE_EXIT { fclose(f); };
 | 
					                    ON_SCOPE_EXIT { fs::CloseFile(file); };
 | 
				
			||||||
 | 
					                    R_TRY(fs::WriteFile(file, 0, buf, size, fs::WriteOption::Flush));
 | 
				
			||||||
                    R_UNLESS(fwrite(buffer.Get(), buffer.GetSize(), 1, f) == 1, fsdevGetLastResult());
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Try to delete the saved archive, but allow deletion failure. */
 | 
					                return ResultSuccess();
 | 
				
			||||||
                std::remove(this->path.Get());
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Rename the path. */
 | 
					            Result Commit(const AutoBuffer &buffer, bool destructive) {
 | 
				
			||||||
                R_UNLESS(std::rename(this->temp_path.Get(), this->path.Get()) == 0, fsdevGetLastResult());
 | 
					                if (destructive) {
 | 
				
			||||||
 | 
					                    /* Delete and save to the real archive. */
 | 
				
			||||||
 | 
					                    R_TRY(SaveArchiveToFile(this->path.Get(), buffer.Get(), buffer.GetSize()));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    /* Delete and save to a temporary archive. */
 | 
				
			||||||
 | 
					                    R_TRY(SaveArchiveToFile(this->temp_path.Get(), buffer.Get(), buffer.GetSize()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* Try to delete the saved archive, but allow deletion failure. */
 | 
				
			||||||
 | 
					                    fs::DeleteFile(this->path.Get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* Rename the path. */
 | 
				
			||||||
 | 
					                    R_TRY(fs::RenameFile(this->temp_path.Get(), this->path.Get()));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -505,18 +515,17 @@ namespace ams::kvdb {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            Result ReadArchiveFile(AutoBuffer *dst) const {
 | 
					            Result ReadArchiveFile(AutoBuffer *dst) const {
 | 
				
			||||||
                /* Open the file. */
 | 
					                /* Open the file. */
 | 
				
			||||||
                FILE *f = fopen(this->path, "rb");
 | 
					                fs::FileHandle file;
 | 
				
			||||||
                R_UNLESS(f != nullptr, fsdevGetLastResult());
 | 
					                R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read));
 | 
				
			||||||
                ON_SCOPE_EXIT { fclose(f); };
 | 
					                ON_SCOPE_EXIT { fs::CloseFile(file); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Get the archive file size. */
 | 
					                /* Get the archive file size. */
 | 
				
			||||||
                fseek(f, 0, SEEK_END);
 | 
					                s64 archive_size;
 | 
				
			||||||
                const size_t archive_size = ftell(f);
 | 
					                R_TRY(fs::GetFileSize(std::addressof(archive_size), file));
 | 
				
			||||||
                fseek(f, 0, SEEK_SET);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Make a new buffer, read the file. */
 | 
					                /* Make a new buffer, read the file. */
 | 
				
			||||||
                R_TRY(dst->Initialize(archive_size));
 | 
					                R_TRY(dst->Initialize(static_cast<size_t>(archive_size)));
 | 
				
			||||||
                R_UNLESS(fread(dst->Get(), archive_size, 1, f) == 1, fsdevGetLastResult());
 | 
					                R_TRY(fs::ReadFile(file, 0, dst->Get(), dst->GetSize()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return ResultSuccess();
 | 
					                return ResultSuccess();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "ldr_types.hpp"
 | 
					#include <stratosphere/ldr/ldr_types.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::ldr::pm {
 | 
					namespace ams::ldr::pm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,8 +16,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <vapours.hpp>
 | 
					#include <vapours.hpp>
 | 
				
			||||||
#include "../ncm/ncm_types.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
#include "../sf/sf_buffer_tags.hpp"
 | 
					#include <stratosphere/ncm/ncm_program_location.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::ldr {
 | 
					namespace ams::ldr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								libstratosphere/include/stratosphere/lr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								libstratosphere/include/stratosphere/lr.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2019 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_api.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_location_resolver_manager_impl.hpp>
 | 
				
			||||||
@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_add_on_content_location_resolver.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class AddOnContentLocationResolver {
 | 
				
			||||||
 | 
					        NON_COPYABLE(AddOnContentLocationResolver);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<IAddOnContentLocationResolver> interface;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            AddOnContentLocationResolver() { /* ... */ }
 | 
				
			||||||
 | 
					            explicit AddOnContentLocationResolver(std::shared_ptr<IAddOnContentLocationResolver> intf) : interface(std::move(intf)) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AddOnContentLocationResolver(AddOnContentLocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                this->interface = std::move(rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AddOnContentLocationResolver &operator=(AddOnContentLocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                AddOnContentLocationResolver(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(AddOnContentLocationResolver &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->interface, rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            Result ResolveAddOnContentPath(Path *out, ncm::DataId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->ResolveAddOnContentPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RegisterAddOnContentStorage(ncm::DataId id, ncm::ApplicationId application_id, ncm::StorageId storage_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterAddOnContentStorage(id, application_id, storage_id);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterAddOnContentStorageDeprecated(id, storage_id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result UnregisterAllAddOnContentPath() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->UnregisterAllAddOnContentPath();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RefreshApplicationAddOnContent(const ncm::ApplicationId *ids, size_t num_ids) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->RefreshApplicationAddOnContent(sf::InArray<ncm::ApplicationId>(ids, num_ids));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result UnregisterApplicationAddOnContent(ncm::ApplicationId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->UnregisterApplicationAddOnContent(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								libstratosphere/include/stratosphere/lr/lr_api.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								libstratosphere/include/stratosphere/lr/lr_api.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_location_resolver.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_add_on_content_location_resolver.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_registered_location_resolver.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Management. */
 | 
				
			||||||
 | 
					    void Initialize();
 | 
				
			||||||
 | 
					    void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Service API. */
 | 
				
			||||||
 | 
					    Result OpenLocationResolver(LocationResolver *out, ncm::StorageId storage_id);
 | 
				
			||||||
 | 
					    Result OpenRegisteredLocationResolver(RegisteredLocationResolver *out);
 | 
				
			||||||
 | 
					    Result OpenAddOnContentLocationResolver(AddOnContentLocationResolver *out);
 | 
				
			||||||
 | 
					    Result RefreshLocationResolver(ncm::StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IAddOnContentLocationResolver : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                ResolveAddOnContentPath                  = 0,
 | 
				
			||||||
 | 
					                RegisterAddOnContentStorageDeprecated    = 1,
 | 
				
			||||||
 | 
					                RegisterAddOnContentStorage              = 1,
 | 
				
			||||||
 | 
					                UnregisterAllAddOnContentPath            = 2,
 | 
				
			||||||
 | 
					                RefreshApplicationAddOnContent           = 3,
 | 
				
			||||||
 | 
					                UnregisterApplicationAddOnContent        = 4,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result ResolveAddOnContentPath(sf::Out<Path> out, ncm::DataId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterAddOnContentStorageDeprecated(ncm::DataId id, ncm::StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterAddOnContentStorage(ncm::DataId id, ncm::ApplicationId application_id, ncm::StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result UnregisterAllAddOnContentPath() = 0;
 | 
				
			||||||
 | 
					            virtual Result RefreshApplicationAddOnContent(const sf::InArray<ncm::ApplicationId> &ids) = 0;
 | 
				
			||||||
 | 
					            virtual Result UnregisterApplicationAddOnContent(ncm::ApplicationId id) = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveAddOnContentPath,               hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorageDeprecated, hos::Version_200, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterAddOnContentStorage,           hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(UnregisterAllAddOnContentPath,         hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RefreshApplicationAddOnContent,        hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(UnregisterApplicationAddOnContent,     hos::Version_900),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ILocationResolver : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        NON_COPYABLE(ILocationResolver);
 | 
				
			||||||
 | 
					        NON_MOVEABLE(ILocationResolver);
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                ResolveProgramPath                                   = 0,
 | 
				
			||||||
 | 
					                RedirectProgramPath                                  = 1,
 | 
				
			||||||
 | 
					                ResolveApplicationControlPath                        = 2,
 | 
				
			||||||
 | 
					                ResolveApplicationHtmlDocumentPath                   = 3,
 | 
				
			||||||
 | 
					                ResolveDataPath                                      = 4,
 | 
				
			||||||
 | 
					                RedirectApplicationControlPathDeprecated             = 5,
 | 
				
			||||||
 | 
					                RedirectApplicationControlPath                       = 5,
 | 
				
			||||||
 | 
					                RedirectApplicationHtmlDocumentPathDeprecated        = 6,
 | 
				
			||||||
 | 
					                RedirectApplicationHtmlDocumentPath                  = 6,
 | 
				
			||||||
 | 
					                ResolveApplicationLegalInformationPath               = 7,
 | 
				
			||||||
 | 
					                RedirectApplicationLegalInformationPathDeprecated    = 8,
 | 
				
			||||||
 | 
					                RedirectApplicationLegalInformationPath              = 8,
 | 
				
			||||||
 | 
					                Refresh                                              = 9,
 | 
				
			||||||
 | 
					                RedirectApplicationProgramPathDeprecated             = 10,
 | 
				
			||||||
 | 
					                RedirectApplicationProgramPath                       = 10,
 | 
				
			||||||
 | 
					                ClearApplicationRedirectionDeprecated                = 11,
 | 
				
			||||||
 | 
					                ClearApplicationRedirection                          = 11,
 | 
				
			||||||
 | 
					                EraseProgramRedirection                              = 12,
 | 
				
			||||||
 | 
					                EraseApplicationControlRedirection                   = 13,
 | 
				
			||||||
 | 
					                EraseApplicationHtmlDocumentRedirection              = 14,
 | 
				
			||||||
 | 
					                EraseApplicationLegalInformationRedirection          = 15,
 | 
				
			||||||
 | 
					                ResolveProgramPathForDebug                           = 16,
 | 
				
			||||||
 | 
					                RedirectProgramPathForDebug                          = 17,
 | 
				
			||||||
 | 
					                RedirectApplicationProgramPathForDebugDeprecated     = 18,
 | 
				
			||||||
 | 
					                RedirectApplicationProgramPathForDebug               = 18,
 | 
				
			||||||
 | 
					                EraseProgramRedirectionForDebug                      = 19,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            ILocationResolver() { /* ... */ }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result ResolveProgramPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectProgramPath(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveApplicationControlPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveApplicationHtmlDocumentPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveDataPath(sf::Out<Path> out, ncm::DataId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationControlPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationControlPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationHtmlDocumentPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveApplicationLegalInformationPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationLegalInformationPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationLegalInformationPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result Refresh() = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationProgramPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ClearApplicationRedirectionDeprecated() = 0;
 | 
				
			||||||
 | 
					            virtual Result ClearApplicationRedirection(const sf::InArray<ncm::ProgramId> &excluding_ids) = 0;
 | 
				
			||||||
 | 
					            virtual Result EraseProgramRedirection(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result EraseApplicationControlRedirection(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result EraseApplicationHtmlDocumentRedirection(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result EraseApplicationLegalInformationRedirection(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveProgramPathForDebug(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectProgramPathForDebug(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationProgramPathForDebugDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result EraseProgramRedirectionForDebug(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveProgramPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectProgramPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveApplicationControlPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveApplicationHtmlDocumentPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveDataPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPathDeprecated,          hos::Version_100, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationControlPath,                    hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPathDeprecated,     hos::Version_100, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationHtmlDocumentPath,               hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveApplicationLegalInformationPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPathDeprecated, hos::Version_100, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationLegalInformationPath,           hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Refresh),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathDeprecated,          hos::Version_500, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPath,                    hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ClearApplicationRedirectionDeprecated,             hos::Version_500, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ClearApplicationRedirection,                       hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(EraseProgramRedirection,                           hos::Version_500),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(EraseApplicationControlRedirection,                hos::Version_500),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(EraseApplicationHtmlDocumentRedirection,           hos::Version_500),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(EraseApplicationLegalInformationRedirection,       hos::Version_500),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveProgramPathForDebug,                        hos::Version_700),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectProgramPathForDebug,                       hos::Version_700),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebugDeprecated,  hos::Version_700, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectApplicationProgramPathForDebug,            hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(EraseProgramRedirectionForDebug,                   hos::Version_700),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_location_resolver.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_add_on_content_location_resolver.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_registered_location_resolver.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ILocationResolverManager : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                OpenLocationResolver                = 0,
 | 
				
			||||||
 | 
					                OpenRegisteredLocationResolver      = 1,
 | 
				
			||||||
 | 
					                RefreshLocationResolver             = 2,
 | 
				
			||||||
 | 
					                OpenAddOnContentLocationResolver    = 3,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result OpenLocationResolver(sf::Out<std::shared_ptr<ILocationResolver>> out, ncm::StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result OpenRegisteredLocationResolver(sf::Out<std::shared_ptr<IRegisteredLocationResolver>> out) = 0;
 | 
				
			||||||
 | 
					            virtual Result RefreshLocationResolver(ncm::StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result OpenAddOnContentLocationResolver(sf::Out<std::shared_ptr<IAddOnContentLocationResolver>> out) = 0;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IRegisteredLocationResolver : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                ResolveProgramPath                    = 0,
 | 
				
			||||||
 | 
					                RegisterProgramPathDeprecated         = 1,
 | 
				
			||||||
 | 
					                RegisterProgramPath                   = 1,
 | 
				
			||||||
 | 
					                UnregisterProgramPath                 = 2,
 | 
				
			||||||
 | 
					                RedirectProgramPathDeprecated         = 3,
 | 
				
			||||||
 | 
					                RedirectProgramPath                   = 3,
 | 
				
			||||||
 | 
					                ResolveHtmlDocumentPath               = 4,
 | 
				
			||||||
 | 
					                RegisterHtmlDocumentPathDeprecated    = 5,
 | 
				
			||||||
 | 
					                RegisterHtmlDocumentPath              = 5,
 | 
				
			||||||
 | 
					                UnregisterHtmlDocumentPath            = 6,
 | 
				
			||||||
 | 
					                RedirectHtmlDocumentPathDeprecated    = 7,
 | 
				
			||||||
 | 
					                RedirectHtmlDocumentPath              = 7,
 | 
				
			||||||
 | 
					                Refresh                               = 8,
 | 
				
			||||||
 | 
					                RefreshExcluding                      = 9,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result ResolveProgramPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterProgramPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result UnregisterProgramPath(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectProgramPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ResolveHtmlDocumentPath(sf::Out<Path> out, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterHtmlDocumentPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RegisterHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result UnregisterHtmlDocumentPath(ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectHtmlDocumentPathDeprecated(const Path &path, ncm::ProgramId id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RedirectHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result Refresh() = 0;
 | 
				
			||||||
 | 
					            virtual Result RefreshExcluding(const sf::InArray<ncm::ProgramId> &ids) = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveProgramPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterProgramPathDeprecated,      hos::Version_100, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterProgramPath,                hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(UnregisterProgramPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectProgramPathDeprecated,      hos::Version_100, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectProgramPath,                hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ResolveHtmlDocumentPath,            hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPathDeprecated, hos::Version_200, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RegisterHtmlDocumentPath,           hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(UnregisterHtmlDocumentPath,         hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPathDeprecated, hos::Version_200, hos::Version_810),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RedirectHtmlDocumentPath,           hos::Version_900),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Refresh,                            hos::Version_700),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RefreshExcluding,                   hos::Version_900),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										175
									
								
								libstratosphere/include/stratosphere/lr/lr_location_resolver.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								libstratosphere/include/stratosphere/lr/lr_location_resolver.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_location_resolver.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class LocationResolver {
 | 
				
			||||||
 | 
					        NON_COPYABLE(LocationResolver);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<ILocationResolver> interface;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            LocationResolver() { /* ... */ }
 | 
				
			||||||
 | 
					            explicit LocationResolver(std::shared_ptr<ILocationResolver> intf) : interface(std::move(intf)) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            LocationResolver(LocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                this->interface = std::move(rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            LocationResolver &operator=(LocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                LocationResolver(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(LocationResolver &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->interface, rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            Result ResolveProgramPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveProgramPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectProgramPath(const Path &path, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->RedirectProgramPath(path, id));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveApplicationControlPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveApplicationControlPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveApplicationHtmlDocumentPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveApplicationHtmlDocumentPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveDataPath(Path *out, ncm::DataId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveDataPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectApplicationControlPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationControlPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationControlPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectApplicationHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationHtmlDocumentPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveApplicationLegalInformationPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveApplicationLegalInformationPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectApplicationLegalInformationPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationLegalInformationPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Refresh() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Refresh();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectApplicationProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ClearApplicationRedirection() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                AMS_ASSERT(hos::GetVersion() < hos::Version_900);
 | 
				
			||||||
 | 
					                return this->ClearApplicationRedirection(nullptr, 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ClearApplicationRedirection(const ncm::ProgramId *excluding_ids, size_t num_ids) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    return this->interface->ClearApplicationRedirection(sf::InArray<ncm::ProgramId>(excluding_ids, num_ids));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return this->interface->ClearApplicationRedirectionDeprecated();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EraseProgramRedirection(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->EraseProgramRedirection(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EraseApplicationControlRedirection(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->EraseApplicationControlRedirection(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EraseApplicationHtmlDocumentRedirection(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->EraseApplicationHtmlDocumentRedirection(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EraseApplicationLegalInformationRedirection(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->EraseApplicationLegalInformationRedirection(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveProgramPathForDebug(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ResolveProgramPathForDebug(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectProgramPathForDebug(const Path &path, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->RedirectProgramPathForDebug(path, id));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebug(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectApplicationProgramPathForDebugDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EraseProgramRedirectionForDebug(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->EraseProgramRedirectionForDebug(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_location_resolver_manager.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_bounded_map.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class LocationResolverManagerImpl final : public ILocationResolverManager {
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            /* Resolver storage. */
 | 
				
			||||||
 | 
					            ncm::BoundedMap<ncm::StorageId, std::shared_ptr<ILocationResolver>, 5> location_resolvers;
 | 
				
			||||||
 | 
					            std::shared_ptr<IRegisteredLocationResolver> registered_location_resolver = nullptr;
 | 
				
			||||||
 | 
					            std::shared_ptr<IAddOnContentLocationResolver> add_on_content_location_resolver = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            os::Mutex mutex;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result OpenLocationResolver(sf::Out<std::shared_ptr<ILocationResolver>> out, ncm::StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result OpenRegisteredLocationResolver(sf::Out<std::shared_ptr<IRegisteredLocationResolver>> out) override;
 | 
				
			||||||
 | 
					            virtual Result RefreshLocationResolver(ncm::StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result OpenAddOnContentLocationResolver(sf::Out<std::shared_ptr<IAddOnContentLocationResolver>> out) override;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(OpenLocationResolver),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(OpenRegisteredLocationResolver),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RefreshLocationResolver),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(OpenAddOnContentLocationResolver, hos::Version_200),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_types.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/lr/lr_i_registered_location_resolver.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class RegisteredLocationResolver {
 | 
				
			||||||
 | 
					        NON_COPYABLE(RegisteredLocationResolver);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<IRegisteredLocationResolver> interface;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            RegisteredLocationResolver() { /* ... */ }
 | 
				
			||||||
 | 
					            explicit RegisteredLocationResolver(std::shared_ptr<IRegisteredLocationResolver> intf) : interface(std::move(intf)) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            RegisteredLocationResolver(RegisteredLocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                this->interface = std::move(rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            RegisteredLocationResolver &operator=(RegisteredLocationResolver &&rhs) {
 | 
				
			||||||
 | 
					                RegisteredLocationResolver(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(RegisteredLocationResolver &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->interface, rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            Result ResolveProgramPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->ResolveProgramPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RegisterProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterProgramPath(path, id, owner_id);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterProgramPathDeprecated(path, id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result UnregisterProgramPath(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->UnregisterProgramPath(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectProgramPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectProgramPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectProgramPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ResolveHtmlDocumentPath(Path *out, ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->ResolveHtmlDocumentPath(out, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RegisterHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterHtmlDocumentPath(path, id, owner_id);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return this->interface->RegisterHtmlDocumentPathDeprecated(path, id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result UnregisterHtmlDocumentPath(ncm::ProgramId id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->UnregisterHtmlDocumentPath(id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void RedirectHtmlDocumentPath(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                if (hos::GetVersion() >= hos::Version_900) {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectHtmlDocumentPath(path, id, owner_id));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    R_ABORT_UNLESS(this->interface->RedirectHtmlDocumentPathDeprecated(path, id));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Refresh() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->Refresh();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RefreshExcluding(const ncm::ProgramId *excluding_ids, size_t num_ids) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface);
 | 
				
			||||||
 | 
					                return this->interface->RefreshExcluding(sf::InArray<ncm::ProgramId>(excluding_ids, num_ids));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								libstratosphere/include/stratosphere/lr/lr_types.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libstratosphere/include/stratosphere/lr/lr_types.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_directory.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::lr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct alignas(4) Path : ams::sf::LargeData {
 | 
				
			||||||
 | 
					        char str[fs::EntryNameLengthMax];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr Path Encode(const char *p) {
 | 
				
			||||||
 | 
					            Path path = {};
 | 
				
			||||||
 | 
					            /* Copy C string to path, terminating when a null byte is found. */
 | 
				
			||||||
 | 
					            for (size_t i = 0; i < sizeof(path) - 1; i++) {
 | 
				
			||||||
 | 
					                path.str[i] = p[i];
 | 
				
			||||||
 | 
					                if (p[i] == '\x00') {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return path;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline size_t GetLength() const {
 | 
				
			||||||
 | 
					            /* Determine length from the first null byte occurence. */
 | 
				
			||||||
 | 
					            size_t len = 0;
 | 
				
			||||||
 | 
					            for (size_t i = 0; i < sizeof(this->str) - 1 && this->str[i] != '\x00'; i++) {
 | 
				
			||||||
 | 
					                len++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return len;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr inline bool IsValid() const {
 | 
				
			||||||
 | 
					            /* Determine validity by presence of a terminating null byte. */
 | 
				
			||||||
 | 
					            for (size_t i = 0; i < sizeof(this->str); i++) {
 | 
				
			||||||
 | 
					                if (this->str[i] == '\x00') {
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<Path>::value && sizeof(Path) == fs::EntryNameLengthMax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,4 +16,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ncm/ncm_types.hpp"
 | 
					#include <stratosphere/ncm/ncm_ids.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_program_location.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_auto_buffer.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_make_path.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id_utils.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_database.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_manager_impl.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_api.hpp>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										53
									
								
								libstratosphere/include/stratosphere/ncm/ncm_api.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								libstratosphere/include/stratosphere/ncm/ncm_api.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_database.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_manager.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Management. */
 | 
				
			||||||
 | 
					    void Initialize();
 | 
				
			||||||
 | 
					    void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void InitializeWithObject(std::shared_ptr<IContentManager> manager_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Service API. */
 | 
				
			||||||
 | 
					    Result CreateContentStorage(StorageId storage_id);
 | 
				
			||||||
 | 
					    Result CreateContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result VerifyContentStorage(StorageId storage_id);
 | 
				
			||||||
 | 
					    Result VerifyContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result OpenContentStorage(ContentStorage *out, StorageId storage_id);
 | 
				
			||||||
 | 
					    Result OpenContentMetaDatabase(ContentMetaDatabase *out, StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result CleanupContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ActivateContentStorage(StorageId storage_id);
 | 
				
			||||||
 | 
					    Result InactivateContentStorage(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ActivateContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					    Result InactivateContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result InvalidateRightsIdCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Deprecated API. */
 | 
				
			||||||
 | 
					    Result CloseContentStorageForcibly(StorageId storage_id);
 | 
				
			||||||
 | 
					    Result CloseContentMetaDatabaseForcibly(StorageId storage_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										88
									
								
								libstratosphere/include/stratosphere/ncm/ncm_auto_buffer.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								libstratosphere/include/stratosphere/ncm/ncm_auto_buffer.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class AutoBuffer {
 | 
				
			||||||
 | 
					        NON_COPYABLE(AutoBuffer);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            u8 *buffer;
 | 
				
			||||||
 | 
					            size_t size;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            AutoBuffer() : buffer(nullptr), size(0) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ~AutoBuffer() {
 | 
				
			||||||
 | 
					                this->Reset();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AutoBuffer(AutoBuffer &&rhs) {
 | 
				
			||||||
 | 
					                this->buffer = rhs.buffer;
 | 
				
			||||||
 | 
					                this->size = rhs.size;
 | 
				
			||||||
 | 
					                rhs.buffer = nullptr;
 | 
				
			||||||
 | 
					                rhs.size = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AutoBuffer& operator=(AutoBuffer &&rhs) {
 | 
				
			||||||
 | 
					                AutoBuffer(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(AutoBuffer &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->buffer, rhs.buffer);
 | 
				
			||||||
 | 
					                std::swap(this->size, rhs.size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Reset() {
 | 
				
			||||||
 | 
					                if (this->buffer != nullptr) {
 | 
				
			||||||
 | 
					                    std::free(this->buffer);
 | 
				
			||||||
 | 
					                    this->buffer = nullptr;
 | 
				
			||||||
 | 
					                    this->size = 0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            u8 *Get() const {
 | 
				
			||||||
 | 
					                return this->buffer;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetSize() const {
 | 
				
			||||||
 | 
					                return this->size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Initialize(size_t size) {
 | 
				
			||||||
 | 
					                /* Check that we're not already initialized. */
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->buffer == nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Allocate a buffer. */
 | 
				
			||||||
 | 
					                this->buffer = static_cast<u8 *>(std::malloc(size));
 | 
				
			||||||
 | 
					                R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this->size = size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Initialize(const void *buf, size_t size) {
 | 
				
			||||||
 | 
					                /* Create a new buffer of the right size. */
 | 
				
			||||||
 | 
					                R_TRY(this->Initialize(size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Copy the input data in. */
 | 
				
			||||||
 | 
					                std::memcpy(this->buffer, buf, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<class Key, class Value, size_t N>
 | 
				
			||||||
 | 
					    using BoundedMap = util::BoundedMap<Key, Value, N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_id.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_id.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct alignas(4) ContentId {
 | 
				
			||||||
 | 
					        util::Uuid uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator==(const ContentId& other) const {
 | 
				
			||||||
 | 
					            return this->uuid == other.uuid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator!=(const ContentId& other) const {
 | 
				
			||||||
 | 
					            return this->uuid != other.uuid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator==(const util::Uuid& other) const {
 | 
				
			||||||
 | 
					            return this->uuid == other;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator!=(const util::Uuid& other) const {
 | 
				
			||||||
 | 
					            return this->uuid != other;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(alignof(ContentId) == 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline ContentId InvalidContentId = { util::InvalidUuid };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_rights_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_info_data.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline size_t ContentIdStringLength  = 2 * sizeof(ContentId);
 | 
				
			||||||
 | 
					    constexpr inline size_t RightsIdStringLength   = 2 * sizeof(fs::RightsId);
 | 
				
			||||||
 | 
					    constexpr inline size_t TicketFileStringLength = RightsIdStringLength + 4;
 | 
				
			||||||
 | 
					    constexpr inline size_t CertFileStringLength   = RightsIdStringLength + 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentIdString {
 | 
				
			||||||
 | 
					        char data[ContentIdStringLength + 1];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ContentIdString GetContentIdString(ContentId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void GetStringFromContentId(char *dst, size_t dst_size, ContentId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_type.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentInfo {
 | 
				
			||||||
 | 
					        ContentId content_id;
 | 
				
			||||||
 | 
					        u32 size_low;
 | 
				
			||||||
 | 
					        u16 size_high;
 | 
				
			||||||
 | 
					        ContentType content_type;
 | 
				
			||||||
 | 
					        u8 id_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr const ContentId &GetId() const {
 | 
				
			||||||
 | 
					            return this->content_id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr u64 GetSize() const {
 | 
				
			||||||
 | 
					            return (static_cast<u64>(this->size_high) << 32) | static_cast<u64>(this->size_low);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr ContentType GetType() const {
 | 
				
			||||||
 | 
					            return this->content_type;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr u8 GetIdOffset() const {
 | 
				
			||||||
 | 
					            return this->id_offset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentInfo Make(ContentId id, u64 size, ContentType type, u8 id_ofs = 0) {
 | 
				
			||||||
 | 
					            const u32 size_low  = size & 0xFFFFFFFFu;
 | 
				
			||||||
 | 
					            const u16 size_high = static_cast<u16>(size >> 32);
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                .content_id   = id,
 | 
				
			||||||
 | 
					                .size_low     = size_low,
 | 
				
			||||||
 | 
					                .size_high    = size_high,
 | 
				
			||||||
 | 
					                .content_type = type,
 | 
				
			||||||
 | 
					                .id_offset    = id_ofs,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(sizeof(std::is_pod<ContentInfo>::value));
 | 
				
			||||||
 | 
					    static_assert(sizeof(ContentInfo)  == 0x18);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_info.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_storage_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_key.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Digest {
 | 
				
			||||||
 | 
					        u8 data[crypto::Sha256Generator::HashSize];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct PackagedContentInfo {
 | 
				
			||||||
 | 
					        Digest digest;
 | 
				
			||||||
 | 
					        ContentInfo info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr const ContentId &GetId() const {
 | 
				
			||||||
 | 
					            return this->info.GetId();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr const ContentType GetType() const {
 | 
				
			||||||
 | 
					            return this->info.GetType();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr const u8 GetIdOffset() const {
 | 
				
			||||||
 | 
					            return this->info.GetIdOffset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_database.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_storage.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ContentMetaDatabaseBuilder {
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            ContentMetaDatabase *db;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            Result BuildFromPackageContentMeta(void *buf, size_t size, const ContentInfo &meta_info);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            explicit ContentMetaDatabaseBuilder(ContentMetaDatabase *d) : db(d) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result BuildFromStorage(ContentStorage *storage);
 | 
				
			||||||
 | 
					            Result BuildFromPackage(const char *package_root_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Cleanup();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ListApplicationPackage(s32 *out_count, ApplicationId *out_ids, s32 max_out_ids, const char *package_root_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentManagerConfig {
 | 
				
			||||||
 | 
					        bool build_system_database;
 | 
				
			||||||
 | 
					        bool import_database_from_system_on_sd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool HasAnyConfig() const {
 | 
				
			||||||
 | 
					            return this->ShouldBuildDatabase() || this->import_database_from_system_on_sd;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool ShouldBuildDatabase() const {
 | 
				
			||||||
 | 
					            return hos::GetVersion() < hos::Version_400 || this->build_system_database;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool ShouldImportDatabaseFromSignedSystemPartitionOnSd() const {
 | 
				
			||||||
 | 
					            return this->import_database_from_system_on_sd;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_mount.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_bis.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_system_save_data.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_manager.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_manager_config.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_database.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_bounded_map.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_rights_id_cache.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_management_utils.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/kvdb/kvdb_memory_key_value_store.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SystemSaveDataInfo {
 | 
				
			||||||
 | 
					        u64 id;
 | 
				
			||||||
 | 
					        u64 size;
 | 
				
			||||||
 | 
					        u64 journal_size;
 | 
				
			||||||
 | 
					        u32 flags;
 | 
				
			||||||
 | 
					        fs::SaveDataSpaceId space_id;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<SystemSaveDataInfo>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ContentManagerImpl final : public IContentManager {
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            constexpr static size_t MaxContentStorageRoots         = 8;
 | 
				
			||||||
 | 
					            constexpr static size_t MaxContentMetaDatabaseRoots    = 8;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            struct ContentStorageRoot {
 | 
				
			||||||
 | 
					                NON_COPYABLE(ContentStorageRoot);
 | 
				
			||||||
 | 
					                NON_MOVEABLE(ContentStorageRoot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                char mount_name[fs::MountNameLengthMax + 1];
 | 
				
			||||||
 | 
					                char path[128];
 | 
				
			||||||
 | 
					                StorageId storage_id;
 | 
				
			||||||
 | 
					                fs::ContentStorageId content_storage_id;
 | 
				
			||||||
 | 
					                std::shared_ptr<IContentStorage> content_storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ContentStorageRoot() { /* ... */ }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct ContentMetaDatabaseRoot {
 | 
				
			||||||
 | 
					                NON_COPYABLE(ContentMetaDatabaseRoot);
 | 
				
			||||||
 | 
					                NON_MOVEABLE(ContentMetaDatabaseRoot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                char mount_name[fs::MountNameLengthMax + 1];
 | 
				
			||||||
 | 
					                char path[128];
 | 
				
			||||||
 | 
					                StorageId storage_id;
 | 
				
			||||||
 | 
					                SystemSaveDataInfo info;
 | 
				
			||||||
 | 
					                std::shared_ptr<IContentMetaDatabase> content_meta_database;
 | 
				
			||||||
 | 
					                std::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
 | 
				
			||||||
 | 
					                u32 max_content_metas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ContentMetaDatabaseRoot() { /* ... */ }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            os::RecursiveMutex mutex;
 | 
				
			||||||
 | 
					            bool initialized;
 | 
				
			||||||
 | 
					            ContentStorageRoot content_storage_roots[MaxContentStorageRoots];
 | 
				
			||||||
 | 
					            ContentMetaDatabaseRoot content_meta_database_roots[MaxContentMetaDatabaseRoots];
 | 
				
			||||||
 | 
					            u32 num_content_storage_entries;
 | 
				
			||||||
 | 
					            u32 num_content_meta_entries;
 | 
				
			||||||
 | 
					            RightsIdCache rights_id_cache;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            ContentManagerImpl() : initialized(false) { /* ... */ };
 | 
				
			||||||
 | 
					            ~ContentManagerImpl();
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            Result Initialize(const ContentManagerConfig &config);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            /* Helpers. */
 | 
				
			||||||
 | 
					            Result GetContentStorageRoot(ContentStorageRoot **out, StorageId id);
 | 
				
			||||||
 | 
					            Result GetContentMetaDatabaseRoot(ContentMetaDatabaseRoot **out, StorageId id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, fs::ContentStorageId content_storage_id);
 | 
				
			||||||
 | 
					            Result InitializeGameCardContentStorageRoot(ContentStorageRoot *out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, const SystemSaveDataInfo &info, size_t max_content_metas);
 | 
				
			||||||
 | 
					            Result InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result BuildContentMetaDatabase(StorageId storage_id);
 | 
				
			||||||
 | 
					            Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
 | 
				
			||||||
 | 
					            Result ImportContentMetaDatabaseImpl(StorageId storage_id, const char *import_mount_name, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result EnsureAndMountSystemSaveData(const char *mount, const SystemSaveDataInfo &info) const;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result CreateContentStorage(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result CreateContentMetaDatabase(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result VerifyContentStorage(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result VerifyContentMetaDatabase(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result CloseContentStorageForcibly(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result CleanupContentMetaDatabase(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result ActivateContentStorage(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result InactivateContentStorage(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result ActivateContentMetaDatabase(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result InactivateContentMetaDatabase(StorageId storage_id) override;
 | 
				
			||||||
 | 
					            virtual Result InvalidateRightsIdCache() override;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										315
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,315 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2018-2020 Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_key.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_info.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_info_data.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_storage_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum ContentMetaAttribute : u8 {
 | 
				
			||||||
 | 
					        ContentMetaAttribute_None                   = (0 << 0),
 | 
				
			||||||
 | 
					        ContentMetaAttribute_IncludesExFatDriver    = (1 << 0),
 | 
				
			||||||
 | 
					        ContentMetaAttribute_Rebootless             = (1 << 1),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentMetaInfo {
 | 
				
			||||||
 | 
					        u64 id;
 | 
				
			||||||
 | 
					        u32 version;
 | 
				
			||||||
 | 
					        ContentMetaType type;
 | 
				
			||||||
 | 
					        u8 attributes;
 | 
				
			||||||
 | 
					        u8 padding[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaInfo Make(u64 id, u32 version, ContentMetaType type, u8 attributes) {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                .id         = id,
 | 
				
			||||||
 | 
					                .version    = version,
 | 
				
			||||||
 | 
					                .type       = type,
 | 
				
			||||||
 | 
					                .attributes = attributes,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr ContentMetaKey ToKey() {
 | 
				
			||||||
 | 
					            return ContentMetaKey::Make(this->id, this->version, this->type);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(sizeof(ContentMetaInfo) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentMetaHeader {
 | 
				
			||||||
 | 
					        u16 extended_header_size;
 | 
				
			||||||
 | 
					        u16 content_count;
 | 
				
			||||||
 | 
					        u16 content_meta_count;
 | 
				
			||||||
 | 
					        u8 attributes;
 | 
				
			||||||
 | 
					        StorageId storage_id;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(sizeof(ContentMetaHeader) == 0x8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct PackagedContentMetaHeader {
 | 
				
			||||||
 | 
					        u64 id;
 | 
				
			||||||
 | 
					        u32 version;
 | 
				
			||||||
 | 
					        ContentMetaType type;
 | 
				
			||||||
 | 
					        u8 reserved_0D;
 | 
				
			||||||
 | 
					        u16 extended_header_size;
 | 
				
			||||||
 | 
					        u16 content_count;
 | 
				
			||||||
 | 
					        u16 content_meta_count;
 | 
				
			||||||
 | 
					        u8 attributes;
 | 
				
			||||||
 | 
					        u8 storage_id;
 | 
				
			||||||
 | 
					        ContentInstallType install_type;
 | 
				
			||||||
 | 
					        u8 reserved_17;
 | 
				
			||||||
 | 
					        u32 required_download_system_version;
 | 
				
			||||||
 | 
					        u8 reserved_1C[4];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(PackagedContentMetaHeader) == 0x20);
 | 
				
			||||||
 | 
					    static_assert(OFFSETOF(PackagedContentMetaHeader, reserved_0D) == 0x0D);
 | 
				
			||||||
 | 
					    static_assert(OFFSETOF(PackagedContentMetaHeader, reserved_17) == 0x17);
 | 
				
			||||||
 | 
					    static_assert(OFFSETOF(PackagedContentMetaHeader, reserved_1C) == 0x1C);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ApplicationMetaExtendedHeader {
 | 
				
			||||||
 | 
					        PatchId patch_id;
 | 
				
			||||||
 | 
					        u32 required_system_version;
 | 
				
			||||||
 | 
					        u32 required_application_version;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct PatchMetaExtendedHeader {
 | 
				
			||||||
 | 
					        ApplicationId application_id;
 | 
				
			||||||
 | 
					        u32 required_system_version;
 | 
				
			||||||
 | 
					        u32 extended_data_size;
 | 
				
			||||||
 | 
					        u8 reserved[0x8];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AddOnContentMetaExtendedHeader {
 | 
				
			||||||
 | 
					        ApplicationId application_id;
 | 
				
			||||||
 | 
					        u32 required_application_version;
 | 
				
			||||||
 | 
					        u32 padding;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct DeltaMetaExtendedHeader {
 | 
				
			||||||
 | 
					        ApplicationId application_id;
 | 
				
			||||||
 | 
					        u32 extended_data_size;
 | 
				
			||||||
 | 
					        u32 padding;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ContentMetaHeaderType, typename ContentInfoType>
 | 
				
			||||||
 | 
					    class ContentMetaAccessor {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            using HeaderType = ContentMetaHeaderType;
 | 
				
			||||||
 | 
					            using InfoType   = ContentInfoType;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            void *data;
 | 
				
			||||||
 | 
					            const size_t size;
 | 
				
			||||||
 | 
					            bool is_header_valid;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            static size_t GetExtendedHeaderSize(ContentMetaType type) {
 | 
				
			||||||
 | 
					                switch (type) {
 | 
				
			||||||
 | 
					                    case ContentMetaType::Application:  return sizeof(ApplicationMetaExtendedHeader);
 | 
				
			||||||
 | 
					                    case ContentMetaType::Patch:        return sizeof(PatchMetaExtendedHeader);
 | 
				
			||||||
 | 
					                    case ContentMetaType::AddOnContent: return sizeof(AddOnContentMetaExtendedHeader);
 | 
				
			||||||
 | 
					                    case ContentMetaType::Delta:        return sizeof(DeltaMetaExtendedHeader);
 | 
				
			||||||
 | 
					                    default:                            return 0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            constexpr ContentMetaAccessor(const void *d, size_t sz) : data(const_cast<void *>(d)), size(sz), is_header_valid(true) { /* ... */ }
 | 
				
			||||||
 | 
					            constexpr ContentMetaAccessor(void *d, size_t sz) : data(d), size(sz), is_header_valid(false) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            template<class NewHeaderType, class NewInfoType>
 | 
				
			||||||
 | 
					            static constexpr size_t CalculateSizeImpl(size_t ext_header_size, size_t content_count, size_t content_meta_count, size_t extended_data_size, bool has_digest) {
 | 
				
			||||||
 | 
					                return sizeof(NewHeaderType) + ext_header_size + content_count * sizeof(NewInfoType) + content_meta_count * sizeof(ContentMetaInfo) + extended_data_size + (has_digest ? sizeof(Digest) : 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr size_t CalculateSize(ContentMetaType type, size_t content_count, size_t content_meta_count, size_t extended_data_size, bool has_digest = false) {
 | 
				
			||||||
 | 
					                return CalculateSizeImpl<ContentMetaHeaderType, ContentInfoType>(GetExtendedHeaderSize(type), content_count, content_meta_count, extended_data_size, has_digest);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetExtendedHeaderAddress() const {
 | 
				
			||||||
 | 
					                return reinterpret_cast<uintptr_t>(this->data) + sizeof(HeaderType);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetContentInfoStartAddress() const {
 | 
				
			||||||
 | 
					                return this->GetExtendedHeaderAddress() + this->GetExtendedHeaderSize();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetContentInfoAddress(size_t i) const {
 | 
				
			||||||
 | 
					                return this->GetContentInfoStartAddress() + i * sizeof(InfoType);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetContentMetaInfoStartAddress() const {
 | 
				
			||||||
 | 
					                return this->GetContentInfoAddress(this->GetContentCount());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetContentMetaInfoAddress(size_t i) const {
 | 
				
			||||||
 | 
					                return this->GetContentMetaInfoStartAddress() + i * sizeof(ContentMetaInfo);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetExtendedDataAddress() const {
 | 
				
			||||||
 | 
					                return this->GetContentMetaInfoAddress(this->GetContentMetaCount());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uintptr_t GetDigestAddress() const {
 | 
				
			||||||
 | 
					                return this->GetExtendedDataAddress() + this->GetExtendedDataSize();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            InfoType *GetWritableContentInfo(size_t i) const {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(i < this->GetContentCount());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return reinterpret_cast<InfoType *>(this->GetContentInfoAddress(i));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            InfoType *GetWritableContentInfo(ContentType type) const {
 | 
				
			||||||
 | 
					                InfoType *found = nullptr;
 | 
				
			||||||
 | 
					                for (size_t i = 0; i < this->GetContentCount(); i++) {
 | 
				
			||||||
 | 
					                    /* We want to find the info with the lowest id offset and the correct type. */
 | 
				
			||||||
 | 
					                    InfoType *info = this->GetWritableContentInfo(i);
 | 
				
			||||||
 | 
					                    if (info->GetType() == type && (found == nullptr || info->GetIdOffset() < found->GetIdOffset())) {
 | 
				
			||||||
 | 
					                        found = info;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return found;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            InfoType *GetWritableContentInfo(ContentType type, u8 id_ofs) const {
 | 
				
			||||||
 | 
					                for (size_t i = 0; i < this->GetContentCount(); i++) {
 | 
				
			||||||
 | 
					                    /* We want to find the info with the correct id offset and the correct type. */
 | 
				
			||||||
 | 
					                    if (InfoType *info = this->GetWritableContentInfo(i); info->GetType() == type && info->GetIdOffset() == id_ofs) {
 | 
				
			||||||
 | 
					                        return info;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return nullptr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            const void *GetData() const {
 | 
				
			||||||
 | 
					                return this->data;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetSize() const {
 | 
				
			||||||
 | 
					                return this->size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const HeaderType *GetHeader() const {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(this->is_header_valid);
 | 
				
			||||||
 | 
					                return static_cast<const HeaderType *>(this->data);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ContentMetaKey GetKey() const {
 | 
				
			||||||
 | 
					                auto header = this->GetHeader();
 | 
				
			||||||
 | 
					                return ContentMetaKey::Make(header->id, header->version, header->type, header->install_type);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetExtendedHeaderSize() const {
 | 
				
			||||||
 | 
					                return this->GetHeader()->extended_header_size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            template<typename ExtendedHeaderType>
 | 
				
			||||||
 | 
					            const ExtendedHeaderType *GetExtendedHeader() const {
 | 
				
			||||||
 | 
					                return reinterpret_cast<const ExtendedHeaderType *>(this->GetExtendedHeaderAddress());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetContentCount() const {
 | 
				
			||||||
 | 
					                return this->GetHeader()->content_count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const InfoType *GetContentInfo(size_t i) const {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(i < this->GetContentCount());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return this->GetWritableContentInfo(i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const InfoType *GetContentInfo(ContentType type) const {
 | 
				
			||||||
 | 
					                return this->GetWritableContentInfo(type);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const InfoType *GetContentInfo(ContentType type, u8 id_ofs) const {
 | 
				
			||||||
 | 
					                return this->GetWritableContentInfo(type, id_ofs);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetContentMetaCount() const {
 | 
				
			||||||
 | 
					                return this->GetHeader()->content_meta_count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const ContentMetaInfo *GetContentMetaInfo(size_t i) const {
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(i < this->GetContentMetaCount());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return reinterpret_cast<const ContentMetaInfo *>(this->GetContentMetaInfoAddress(i));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t GetExtendedDataSize() const {
 | 
				
			||||||
 | 
					                switch (this->GetHeader()->type) {
 | 
				
			||||||
 | 
					                    case ContentMetaType::Patch: return this->GetExtendedHeader<PatchMetaExtendedHeader>()->extended_data_size;
 | 
				
			||||||
 | 
					                    case ContentMetaType::Delta: return this->GetExtendedHeader<DeltaMetaExtendedHeader>()->extended_data_size;
 | 
				
			||||||
 | 
					                    default:                     return 0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const void *GetExtendedData() const {
 | 
				
			||||||
 | 
					                return reinterpret_cast<const void *>(this->GetExtendedDataAddress());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const Digest *GetDigest() const {
 | 
				
			||||||
 | 
					                return reinterpret_cast<Digest *>(this->GetDigestAddress());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool HasContent(const ContentId &id) const {
 | 
				
			||||||
 | 
					                for (size_t i = 0; i < this->GetContentCount(); i++) {
 | 
				
			||||||
 | 
					                    if (id == this->GetContentInfo(i)->GetId()) {
 | 
				
			||||||
 | 
					                        return true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::optional<ApplicationId> GetApplicationId(const ContentMetaKey &key) const {
 | 
				
			||||||
 | 
					                switch (key.type) {
 | 
				
			||||||
 | 
					                    case ContentMetaType::Application:  return ApplicationId{ key.id };
 | 
				
			||||||
 | 
					                    case ContentMetaType::Patch:        return this->GetExtendedHeader<PatchMetaExtendedHeader>()->application_id;
 | 
				
			||||||
 | 
					                    case ContentMetaType::AddOnContent: return this->GetExtendedHeader<AddOnContentMetaExtendedHeader>()->application_id;
 | 
				
			||||||
 | 
					                    case ContentMetaType::Delta:        return this->GetExtendedHeader<DeltaMetaExtendedHeader>()->application_id;
 | 
				
			||||||
 | 
					                    default:                            return std::nullopt;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::optional<ApplicationId> GetApplicationId() const {
 | 
				
			||||||
 | 
					                return this->GetApplicationId(this->GetKey());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ContentMetaReader : public ContentMetaAccessor<ContentMetaHeader, ContentInfo> {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            constexpr ContentMetaReader(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using ContentMetaAccessor::CalculateSize;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class PackagedContentMetaReader : public ContentMetaAccessor<PackagedContentMetaHeader, PackagedContentInfo> {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            constexpr PackagedContentMetaReader(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t CalculateConvertContentMetaSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void ConvertToContentMeta(void *dst, size_t size, const ContentInfo &meta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t CountDeltaFragments() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            static constexpr size_t CalculateSize(ContentMetaType type, size_t content_count, size_t content_meta_count, size_t extended_data_size) {
 | 
				
			||||||
 | 
					                return ContentMetaAccessor::CalculateSize(type, content_count, content_meta_count, extended_data_size, true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,194 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ContentMetaDatabase {
 | 
				
			||||||
 | 
					        NON_COPYABLE(ContentMetaDatabase);
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            struct ListCount {
 | 
				
			||||||
 | 
					                s32 written;
 | 
				
			||||||
 | 
					                s32 total;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<IContentMetaDatabase> interface;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            ContentMetaDatabase() { /* ... */ }
 | 
				
			||||||
 | 
					            explicit ContentMetaDatabase(std::shared_ptr<IContentMetaDatabase> intf) : interface(std::move(intf)) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ContentMetaDatabase(ContentMetaDatabase &&rhs) {
 | 
				
			||||||
 | 
					                this->interface = std::move(rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ContentMetaDatabase &operator=(ContentMetaDatabase &&rhs) {
 | 
				
			||||||
 | 
					                ContentMetaDatabase(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(ContentMetaDatabase &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->interface, rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            Result Set(const ContentMetaKey &key, const void *buf, size_t size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Set(key, sf::InBuffer(buf, size));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Get(size_t *out_size, void *dst, size_t dst_size, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                u64 size;
 | 
				
			||||||
 | 
					                R_TRY(this->interface->Get(std::addressof(size), key, sf::OutBuffer(dst, dst_size)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_size = size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #define AMS_NCM_DEFINE_GETTERS(Kind, IdType)                                                                                \
 | 
				
			||||||
 | 
					            Result Get##Kind(ContentId *out, IdType##Id id, u32 version) {                                                              \
 | 
				
			||||||
 | 
					                return this->interface->GetContentIdByType(out, ContentMetaKey::MakeUnknownType(id.value, version), ContentType::Kind); \
 | 
				
			||||||
 | 
					            }                                                                                                                           \
 | 
				
			||||||
 | 
					                                                                                                                                        \
 | 
				
			||||||
 | 
					            Result GetLatest##Kind(ContentId *out, IdType##Id id) {                                                                     \
 | 
				
			||||||
 | 
					                ContentMetaKey latest_key;                                                                                              \
 | 
				
			||||||
 | 
					                R_TRY(this->interface->GetLatestContentMetaKey(std::addressof(latest_key), id.value));                                  \
 | 
				
			||||||
 | 
					                return this->interface->GetContentIdByType(out, latest_key, ContentType::Kind);                                         \
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AMS_NCM_DEFINE_GETTERS(Program,          Program)
 | 
				
			||||||
 | 
					            AMS_NCM_DEFINE_GETTERS(Data,             Data)
 | 
				
			||||||
 | 
					            AMS_NCM_DEFINE_GETTERS(Control,          Application)
 | 
				
			||||||
 | 
					            AMS_NCM_DEFINE_GETTERS(HtmlDocument,     Application)
 | 
				
			||||||
 | 
					            AMS_NCM_DEFINE_GETTERS(LegalInformation, Application)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #undef AMS_NCM_DEFINE_GETTERS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Remove(const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Remove(key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Remove(SystemProgramId id, u32 version) {
 | 
				
			||||||
 | 
					                return this->Remove(ContentMetaKey::Make(id, version));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Remove(SystemDataId id, u32 version) {
 | 
				
			||||||
 | 
					                return this->Remove(ContentMetaKey::Make(id, version));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Remove(ApplicationId id, u32 version) {
 | 
				
			||||||
 | 
					                return this->Remove(ContentMetaKey::Make(id, version));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetContentIdByType(ContentId *out_content_id, const ContentMetaKey &key, ContentType type) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetContentIdByType(out_content_id, key, type);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetContentIdByTypeAndIdOffset(ContentId *out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetContentIdByTypeAndIdOffset(out_content_id, key, type, id_offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ListCount ListApplication(ApplicationContentMetaKey *dst, size_t dst_size) {
 | 
				
			||||||
 | 
					                ListCount lc = {};
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->ListApplication(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ApplicationContentMetaKey>(dst, dst_size), ContentMetaType::Unknown));
 | 
				
			||||||
 | 
					                return lc;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ListCount ListContentMeta(ContentMetaKey *dst, size_t dst_size, ContentMetaType type = ContentMetaType::Unknown, ApplicationId app_id = InvalidApplicationId, u64 min = std::numeric_limits<u64>::min(), u64 max = std::numeric_limits<u64>::max(), ContentInstallType install_type = ContentInstallType::Full) {
 | 
				
			||||||
 | 
					                ListCount lc = {};
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->List(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ContentMetaKey>(dst, dst_size), type, app_id, min, max, install_type));
 | 
				
			||||||
 | 
					                return lc;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetLatest(ContentMetaKey *out_key, u64 id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetLatestContentMetaKey(out_key, id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ListContentInfo(s32 *out_count, ContentInfo *dst, size_t dst_size, const ContentMetaKey &key, s32 offset) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ListContentInfo(out_count, sf::OutArray<ContentInfo>(dst, dst_size), key, offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ListContentMetaInfo(s32 *out_count, ContentMetaInfo *dst, size_t dst_size, const ContentMetaKey &key, s32 offset) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ListContentMetaInfo(out_count, sf::OutArray<ContentMetaInfo>(dst, dst_size), key, offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Has(bool *out, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Has(out, key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result HasAll(bool *out, const ContentMetaKey *keys, size_t num_keys) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->HasAll(out, sf::InArray<ContentMetaKey>(keys, num_keys));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result HasContent(bool *out, const ContentMetaKey &key, const ContentId &content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->HasContent(out, key, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetSize(size_t *out_size, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                u64 size;
 | 
				
			||||||
 | 
					                R_TRY(this->interface->GetSize(std::addressof(size), key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                *out_size = size;
 | 
				
			||||||
 | 
					                return ResultSuccess();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRequiredSystemVersion(u32 *out_version, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetRequiredSystemVersion(out_version, key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetPatchId(PatchId *out_patch_id, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetPatchId(out_patch_id, key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result DisableForcibly() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->DisableForcibly();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result LookupOrphanContent(bool *out_orphaned, ContentId *content_list, size_t count) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->LookupOrphanContent(sf::OutArray<bool>(out_orphaned, count), sf::InArray<ContentId>(content_list, count));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Commit() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Commit();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetAttributes(u8 *out_attributes, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetAttributes(out_attributes, key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRequiredApplicationVersion(u32 *out_version, const ContentMetaKey &key) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetRequiredApplicationVersion(out_version, key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_data_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_program_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ApplicationId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr operator ProgramId() const {
 | 
				
			||||||
 | 
					            return { this->value };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static const ApplicationId Start;
 | 
				
			||||||
 | 
					        static const ApplicationId End;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline const ApplicationId InvalidApplicationId = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr const ApplicationId ApplicationId::Start   = { 0x0100000000010000ul };
 | 
				
			||||||
 | 
					    inline constexpr const ApplicationId ApplicationId::End     = { 0x01FFFFFFFFFFFFFFul };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool IsApplicationId(const ProgramId &program_id) {
 | 
				
			||||||
 | 
					        return ApplicationId::Start <= program_id && program_id <= ApplicationId::End;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool IsApplicationId(const ApplicationId &id) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ApplicationGroupId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct PatchId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr operator ProgramId() const {
 | 
				
			||||||
 | 
					            return { this->value };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct PatchGroupId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AddOnContentId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr operator DataId() const {
 | 
				
			||||||
 | 
					            return { this->value };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct DeltaId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr operator ProgramId() const {
 | 
				
			||||||
 | 
					            return { this->value };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_type.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_system_content_meta_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class ContentInstallType : u8 {
 | 
				
			||||||
 | 
					        Full            = 0,
 | 
				
			||||||
 | 
					        FragmentOnly    = 1,
 | 
				
			||||||
 | 
					        Unknown         = 7,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ContentMetaKey {
 | 
				
			||||||
 | 
					        u64 id;
 | 
				
			||||||
 | 
					        u32 version;
 | 
				
			||||||
 | 
					        ContentMetaType type;
 | 
				
			||||||
 | 
					        ContentInstallType install_type;
 | 
				
			||||||
 | 
					        u8 padding[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator<(const ContentMetaKey& rhs) const {
 | 
				
			||||||
 | 
					            return std::tie(this->id, this->version, this->type, this->install_type) < std::tie(rhs.id, rhs.version, rhs.type, rhs.install_type);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr bool operator==(const ContentMetaKey& rhs) const {
 | 
				
			||||||
 | 
					            return std::tie(this->id, this->version, this->type, this->install_type) == std::tie(rhs.id, rhs.version, rhs.type, rhs.install_type);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr bool operator!=(const ContentMetaKey& rhs) const {
 | 
				
			||||||
 | 
					            return !(*this == rhs);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey MakeUnknownType(u64 id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id, .version = version, .type = ContentMetaType::Unknown };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(u64 id, u32 version, ContentMetaType type) {
 | 
				
			||||||
 | 
					            return { .id = id, .version = version, .type = type };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(u64 id, u32 version, ContentMetaType type, ContentInstallType install_type) {
 | 
				
			||||||
 | 
					            return { .id = id, .version = version, .type = type, .install_type = install_type };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(SystemProgramId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::SystemProgram };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(SystemDataId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::SystemData };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(SystemUpdateId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::SystemUpdate };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(ApplicationId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::Application };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(PatchId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::Patch };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(PatchId id, u32 version, ContentInstallType install_type) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::Patch, .install_type = install_type };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ContentMetaKey Make(DeltaId id, u32 version) {
 | 
				
			||||||
 | 
					            return { .id = id.value, .version = version, .type = ContentMetaType::Delta };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(sizeof(ContentMetaKey) == 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ApplicationContentMetaKey {
 | 
				
			||||||
 | 
					        ContentMetaKey key;
 | 
				
			||||||
 | 
					        ncm::ApplicationId application_id;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(sizeof(ApplicationContentMetaKey) == 0x18);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct StorageContentMetaKey {
 | 
				
			||||||
 | 
					        ContentMetaKey key;
 | 
				
			||||||
 | 
					        StorageId storage_id;
 | 
				
			||||||
 | 
					        u8 reserved[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr bool operator==(StorageContentMetaKey &rhs) const {
 | 
				
			||||||
 | 
					            return this->key == rhs.key && this->storage_id == rhs.storage_id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constexpr bool operator<(StorageContentMetaKey &rhs) const {
 | 
				
			||||||
 | 
					            return this->key == rhs.key ? this->storage_id < rhs.storage_id : this->key < rhs.key;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(StorageContentMetaKey) == 0x18);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class ContentMetaType : u8 {
 | 
				
			||||||
 | 
					        Unknown                 = 0x0,
 | 
				
			||||||
 | 
					        SystemProgram           = 0x1,
 | 
				
			||||||
 | 
					        SystemData              = 0x2,
 | 
				
			||||||
 | 
					        SystemUpdate            = 0x3,
 | 
				
			||||||
 | 
					        BootImagePackage        = 0x4,
 | 
				
			||||||
 | 
					        BootImagePackageSafe    = 0x5,
 | 
				
			||||||
 | 
					        Application             = 0x80,
 | 
				
			||||||
 | 
					        Patch                   = 0x81,
 | 
				
			||||||
 | 
					        AddOnContent            = 0x82,
 | 
				
			||||||
 | 
					        Delta                   = 0x83,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *GetContentMetaTypeString(ContentMetaType type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_auto_buffer.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_storage_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_key.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_database.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ReadContentMetaPath(AutoBuffer *out, const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										200
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_storage.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ContentStorage {
 | 
				
			||||||
 | 
					        NON_COPYABLE(ContentStorage);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            std::shared_ptr<IContentStorage> interface;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            ContentStorage() { /* ... */ }
 | 
				
			||||||
 | 
					            explicit ContentStorage(std::shared_ptr<IContentStorage> intf) : interface(std::move(intf)) { /* ... */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ContentStorage(ContentStorage &&rhs) {
 | 
				
			||||||
 | 
					                this->interface = std::move(rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ContentStorage &operator=(ContentStorage &&rhs) {
 | 
				
			||||||
 | 
					                ContentStorage(std::move(rhs)).Swap(*this);
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Swap(ContentStorage &rhs) {
 | 
				
			||||||
 | 
					                std::swap(this->interface, rhs.interface);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            PlaceHolderId GeneratePlaceHolderId() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                PlaceHolderId id;
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->GeneratePlaceHolderId(std::addressof(id)));
 | 
				
			||||||
 | 
					                return id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->CreatePlaceHolder(placeholder_id, content_id, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result DeletePlaceHolder(PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->DeletePlaceHolder(placeholder_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result HasPlaceHolder(bool *out, PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->HasPlaceHolder(out, placeholder_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const void *buf, size_t size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->WritePlaceHolder(placeholder_id, offset, sf::InBuffer(buf, size));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Register(PlaceHolderId placeholder_id, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Register(placeholder_id, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Delete(ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Delete(content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result Has(bool *out, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->Has(out, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void GetPath(Path *out, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->GetPath(out, content_id));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void GetPlaceHolderPath(Path *out, PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                R_ABORT_UNLESS(this->interface->GetPlaceHolderPath(out, placeholder_id));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result CleanupAllPlaceHolder() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->CleanupAllPlaceHolder();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ListPlaceHolder(s32 *out_count, PlaceHolderId *out_list, size_t out_list_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ListPlaceHolder(out_count, sf::OutArray<PlaceHolderId>(out_list, out_list_size));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetContentCount(s32 *out_count) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetContentCount(out_count);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ListContentId(s32 *out_count, ContentId *out_list, size_t out_list_size, s32 offset) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ListContentId(out_count, sf::OutArray<ContentId>(out_list, out_list_size), offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetSize(s64 *out_size, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetSizeFromContentId(out_size, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetSize(s64 *out_size, PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetSizeFromPlaceHolderId(out_size, placeholder_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result DisableForcibly() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->DisableForcibly();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->RevertToPlaceHolder(placeholder_id, old_content_id, new_content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->SetPlaceHolderSize(placeholder_id, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result ReadContentIdFile(void *dst, size_t size, ContentId content_id, s64 offset) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->ReadContentIdFile(sf::OutBuffer(dst, size), content_id, offset);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRightsId(ams::fs::RightsId *out_rights_id, PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(hos::GetVersion() < hos::Version_300);
 | 
				
			||||||
 | 
					                return this->interface->GetRightsIdFromPlaceHolderIdDeprecated(out_rights_id, placeholder_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRightsId(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(hos::GetVersion() >= hos::Version_300);
 | 
				
			||||||
 | 
					                return this->interface->GetRightsIdFromPlaceHolderId(out_rights_id, placeholder_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRightsId(ams::fs::RightsId *out_rights_id, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(hos::GetVersion() < hos::Version_300);
 | 
				
			||||||
 | 
					                return this->interface->GetRightsIdFromContentIdDeprecated(out_rights_id, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRightsId(ncm::RightsId *out_rights_id, ContentId content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                AMS_ABORT_UNLESS(hos::GetVersion() >= hos::Version_300);
 | 
				
			||||||
 | 
					                return this->interface->GetRightsIdFromContentId(out_rights_id, content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result WriteContentForDebug(ContentId content_id, s64 offset, const void *buf, size_t size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->WriteContentForDebug(content_id, offset, sf::InBuffer(buf, size));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetFreeSpaceSize(s64 *out_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetFreeSpaceSize(out_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetTotalSpaceSize(s64 *out_size) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetTotalSpaceSize(out_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result FlushPlaceHolder() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->FlushPlaceHolder();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result RepairInvalidFileAttribute() {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->RepairInvalidFileAttribute();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Result GetRightsIdFromPlaceHolderIdWithCache(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) {
 | 
				
			||||||
 | 
					                AMS_ASSERT(this->interface != nullptr);
 | 
				
			||||||
 | 
					                return this->interface->GetRightsIdFromPlaceHolderIdWithCache(out_rights_id, placeholder_id, cache_content_id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class ContentType : u8 {
 | 
				
			||||||
 | 
					        Meta                = 0,
 | 
				
			||||||
 | 
					        Program             = 1,
 | 
				
			||||||
 | 
					        Data                = 2,
 | 
				
			||||||
 | 
					        Control             = 3,
 | 
				
			||||||
 | 
					        HtmlDocument        = 4,
 | 
				
			||||||
 | 
					        LegalInformation    = 5,
 | 
				
			||||||
 | 
					        DeltaFragment       = 6,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								libstratosphere/include/stratosphere/ncm/ncm_data_id.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								libstratosphere/include/stratosphere/ncm/ncm_data_id.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct DataId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static const DataId Invalid;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator==(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value == rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator!=(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value != rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator<(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value < rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator<=(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value <= rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator>(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value > rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator>=(const DataId &lhs, const DataId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value >= rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr const DataId DataId::Invalid = {};
 | 
				
			||||||
 | 
					    inline constexpr const DataId InvalidDataId = DataId::Invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_storage.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IContentManager : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                CreateContentStorage                = 0,
 | 
				
			||||||
 | 
					                CreateContentMetaDatabase           = 1,
 | 
				
			||||||
 | 
					                VerifyContentStorage                = 2,
 | 
				
			||||||
 | 
					                VerifyContentMetaDatabase           = 3,
 | 
				
			||||||
 | 
					                OpenContentStorage                  = 4,
 | 
				
			||||||
 | 
					                OpenContentMetaDatabase             = 5,
 | 
				
			||||||
 | 
					                CloseContentStorageForcibly         = 6,
 | 
				
			||||||
 | 
					                CloseContentMetaDatabaseForcibly    = 7,
 | 
				
			||||||
 | 
					                CleanupContentMetaDatabase          = 8,
 | 
				
			||||||
 | 
					                ActivateContentStorage              = 9,
 | 
				
			||||||
 | 
					                InactivateContentStorage            = 10,
 | 
				
			||||||
 | 
					                ActivateContentMetaDatabase         = 11,
 | 
				
			||||||
 | 
					                InactivateContentMetaDatabase       = 12,
 | 
				
			||||||
 | 
					                InvalidateRightsIdCache             = 13,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual Result CreateContentStorage(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result CreateContentMetaDatabase(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result VerifyContentStorage(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result VerifyContentMetaDatabase(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result OpenContentStorage(sf::Out<std::shared_ptr<IContentStorage>> out, StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result OpenContentMetaDatabase(sf::Out<std::shared_ptr<IContentMetaDatabase>> out, StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result CloseContentStorageForcibly(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result CleanupContentMetaDatabase(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ActivateContentStorage(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result InactivateContentStorage(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ActivateContentMetaDatabase(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result InactivateContentMetaDatabase(StorageId storage_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result InvalidateRightsIdCache() = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CreateContentStorage),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CreateContentMetaDatabase),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(VerifyContentStorage),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(VerifyContentMetaDatabase),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(OpenContentStorage),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(OpenContentMetaDatabase),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CloseContentStorageForcibly,      hos::Version_100, hos::Version_100),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CloseContentMetaDatabaseForcibly, hos::Version_100, hos::Version_100),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CleanupContentMetaDatabase),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ActivateContentStorage,           hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(InactivateContentStorage,         hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ActivateContentMetaDatabase,      hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(InactivateContentMetaDatabase,    hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(InvalidateRightsIdCache,          hos::Version_900),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/sf.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IContentMetaDatabase : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                Set                              = 0,
 | 
				
			||||||
 | 
					                Get                              = 1,
 | 
				
			||||||
 | 
					                Remove                           = 2,
 | 
				
			||||||
 | 
					                GetContentIdByType               = 3,
 | 
				
			||||||
 | 
					                ListContentInfo                  = 4,
 | 
				
			||||||
 | 
					                List                             = 5,
 | 
				
			||||||
 | 
					                GetLatestContentMetaKey          = 6,
 | 
				
			||||||
 | 
					                ListApplication                  = 7,
 | 
				
			||||||
 | 
					                Has                              = 8,
 | 
				
			||||||
 | 
					                HasAll                           = 9,
 | 
				
			||||||
 | 
					                GetSize                          = 10,
 | 
				
			||||||
 | 
					                GetRequiredSystemVersion         = 11,
 | 
				
			||||||
 | 
					                GetPatchId                       = 12,
 | 
				
			||||||
 | 
					                DisableForcibly                  = 13,
 | 
				
			||||||
 | 
					                LookupOrphanContent              = 14,
 | 
				
			||||||
 | 
					                Commit                           = 15,
 | 
				
			||||||
 | 
					                HasContent                       = 16,
 | 
				
			||||||
 | 
					                ListContentMetaInfo              = 17,
 | 
				
			||||||
 | 
					                GetAttributes                    = 18,
 | 
				
			||||||
 | 
					                GetRequiredApplicationVersion    = 19,
 | 
				
			||||||
 | 
					                GetContentIdByTypeAndIdOffset    = 20,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            /* Actual commands. */
 | 
				
			||||||
 | 
					            virtual Result Set(const ContentMetaKey &key, sf::InBuffer value) = 0;
 | 
				
			||||||
 | 
					            virtual Result Get(sf::Out<u64> out_size, const ContentMetaKey &key, sf::OutBuffer out_value) = 0;
 | 
				
			||||||
 | 
					            virtual Result Remove(const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetContentIdByType(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type) = 0;
 | 
				
			||||||
 | 
					            virtual Result ListContentInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentInfo> &out_info, const ContentMetaKey &key, s32 offset) = 0;
 | 
				
			||||||
 | 
					            virtual Result List(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaKey> &out_info, ContentMetaType meta_type, ApplicationId application_id, u64 min, u64 max, ContentInstallType install_type) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, u64 id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ListApplication(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ApplicationContentMetaKey> &out_keys, ContentMetaType meta_type) = 0;
 | 
				
			||||||
 | 
					            virtual Result Has(sf::Out<bool> out, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result HasAll(sf::Out<bool> out, const sf::InArray<ContentMetaKey> &keys) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetSize(sf::Out<u64> out_size, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRequiredSystemVersion(sf::Out<u32> out_version, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetPatchId(sf::Out<PatchId> out_patch_id, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result DisableForcibly() = 0;
 | 
				
			||||||
 | 
					            virtual Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids) = 0;
 | 
				
			||||||
 | 
					            virtual Result Commit() = 0;
 | 
				
			||||||
 | 
					            virtual Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result ListContentMetaInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, s32 offset) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetAttributes(sf::Out<u8> out_attributes, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Set),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Get),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Remove),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetContentIdByType),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ListContentInfo),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(List),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetLatestContentMetaKey),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ListApplication),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Has),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(HasAll),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetSize),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRequiredSystemVersion),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetPatchId),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(DisableForcibly),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(LookupOrphanContent),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Commit),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(HasContent),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ListContentMetaInfo),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetAttributes),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRequiredApplicationVersion, hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetContentIdByTypeAndIdOffset, hos::Version_500),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,130 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/sf.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_placeholder_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_path.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_rights_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class IContentStorage : public sf::IServiceObject {
 | 
				
			||||||
 | 
					        NON_COPYABLE(IContentStorage);
 | 
				
			||||||
 | 
					        NON_MOVEABLE(IContentStorage);
 | 
				
			||||||
 | 
					        protected:
 | 
				
			||||||
 | 
					            enum class CommandId {
 | 
				
			||||||
 | 
					                GeneratePlaceHolderId                     = 0,
 | 
				
			||||||
 | 
					                CreatePlaceHolder                         = 1,
 | 
				
			||||||
 | 
					                DeletePlaceHolder                         = 2,
 | 
				
			||||||
 | 
					                HasPlaceHolder                            = 3,
 | 
				
			||||||
 | 
					                WritePlaceHolder                          = 4,
 | 
				
			||||||
 | 
					                Register                                  = 5,
 | 
				
			||||||
 | 
					                Delete                                    = 6,
 | 
				
			||||||
 | 
					                Has                                       = 7,
 | 
				
			||||||
 | 
					                GetPath                                   = 8,
 | 
				
			||||||
 | 
					                GetPlaceHolderPath                        = 9,
 | 
				
			||||||
 | 
					                CleanupAllPlaceHolder                     = 10,
 | 
				
			||||||
 | 
					                ListPlaceHolder                           = 11,
 | 
				
			||||||
 | 
					                GetContentCount                           = 12,
 | 
				
			||||||
 | 
					                ListContentId                             = 13,
 | 
				
			||||||
 | 
					                GetSizeFromContentId                      = 14,
 | 
				
			||||||
 | 
					                DisableForcibly                           = 15,
 | 
				
			||||||
 | 
					                RevertToPlaceHolder                       = 16,
 | 
				
			||||||
 | 
					                SetPlaceHolderSize                        = 17,
 | 
				
			||||||
 | 
					                ReadContentIdFile                         = 18,
 | 
				
			||||||
 | 
					                GetRightsIdFromPlaceHolderIdDeprecated    = 19,
 | 
				
			||||||
 | 
					                GetRightsIdFromPlaceHolderId              = 19,
 | 
				
			||||||
 | 
					                GetRightsIdFromContentIdDeprecated        = 20,
 | 
				
			||||||
 | 
					                GetRightsIdFromContentId                  = 20,
 | 
				
			||||||
 | 
					                WriteContentForDebug                      = 21,
 | 
				
			||||||
 | 
					                GetFreeSpaceSize                          = 22,
 | 
				
			||||||
 | 
					                GetTotalSpaceSize                         = 23,
 | 
				
			||||||
 | 
					                FlushPlaceHolder                          = 24,
 | 
				
			||||||
 | 
					                GetSizeFromPlaceHolderId                  = 25,
 | 
				
			||||||
 | 
					                RepairInvalidFileAttribute                = 26,
 | 
				
			||||||
 | 
					                GetRightsIdFromPlaceHolderIdWithCache     = 27,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            IContentStorage() { /* ... */ }
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            virtual Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out) = 0;
 | 
				
			||||||
 | 
					            virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size) = 0;
 | 
				
			||||||
 | 
					            virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, sf::InBuffer data) = 0;
 | 
				
			||||||
 | 
					            virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result Delete(ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result Has(sf::Out<bool> out, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetPath(sf::Out<Path> out, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result CleanupAllPlaceHolder() = 0;
 | 
				
			||||||
 | 
					            virtual Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetContentCount(sf::Out<s32> out_count) = 0;
 | 
				
			||||||
 | 
					            virtual Result ListContentId(sf::Out<s32> out_count, const sf::OutArray<ContentId> &out_buf, s32 start_offset) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetSizeFromContentId(sf::Out<s64> out_size, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result DisableForcibly() = 0;
 | 
				
			||||||
 | 
					            virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size) = 0;
 | 
				
			||||||
 | 
					            virtual Result ReadContentIdFile(sf::OutBuffer buf, ContentId content_id, s64 offset) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result WriteContentForDebug(ContentId content_id, s64 offset, sf::InBuffer data) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetFreeSpaceSize(sf::Out<s64> out_size) = 0;
 | 
				
			||||||
 | 
					            virtual Result GetTotalSpaceSize(sf::Out<s64> out_size) = 0;
 | 
				
			||||||
 | 
					            virtual Result FlushPlaceHolder() = 0;
 | 
				
			||||||
 | 
					            virtual Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id) = 0;
 | 
				
			||||||
 | 
					            virtual Result RepairInvalidFileAttribute() = 0;
 | 
				
			||||||
 | 
					            virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            DEFINE_SERVICE_DISPATCH_TABLE {
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GeneratePlaceHolderId),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CreatePlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(DeletePlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(HasPlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(WritePlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Register),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Delete),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(Has),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetPlaceHolderPath),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(CleanupAllPlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ListPlaceHolder),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GeneratePlaceHolderId),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetContentCount),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ListContentId),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetSizeFromContentId),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(DisableForcibly),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RevertToPlaceHolder,                       hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(SetPlaceHolderSize,                        hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(ReadContentIdFile,                         hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRightsIdFromPlaceHolderIdDeprecated,    hos::Version_200, hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRightsIdFromPlaceHolderId,              hos::Version_300),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRightsIdFromContentIdDeprecated,        hos::Version_200, hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRightsIdFromContentId,                  hos::Version_300),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(WriteContentForDebug,                      hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetFreeSpaceSize,                          hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetTotalSpaceSize,                         hos::Version_200),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(FlushPlaceHolder,                          hos::Version_300),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetSizeFromPlaceHolderId,                  hos::Version_400),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(RepairInvalidFileAttribute,                hos::Version_400),
 | 
				
			||||||
 | 
					                MAKE_SERVICE_COMMAND_META(GetRightsIdFromPlaceHolderIdWithCache,     hos::Version_800),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								libstratosphere/include/stratosphere/ncm/ncm_ids.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								libstratosphere/include/stratosphere/ncm/ncm_ids.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_data_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_program_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_meta_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_system_content_meta_id.hpp>
 | 
				
			||||||
							
								
								
									
										38
									
								
								libstratosphere/include/stratosphere/ncm/ncm_make_path.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								libstratosphere/include/stratosphere/ncm/ncm_make_path.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_placeholder_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_path_string.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using MakeContentPathFunction        = void (*)(PathString *out, ContentId content_id, const char *root_path);
 | 
				
			||||||
 | 
					    using MakePlaceHolderPathFunction    = void (*)(PathString *out, PlaceHolderId placeholder_id,const char *root_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void MakeFlatContentFilePath(PathString *out, ContentId content_id, const char *root_path);
 | 
				
			||||||
 | 
					    void MakeSha256HierarchicalContentFilePath_ForFat4KCluster(PathString *out, ContentId content_id, const char *root_path);
 | 
				
			||||||
 | 
					    void MakeSha256HierarchicalContentFilePath_ForFat16KCluster(PathString *out, ContentId content_id, const char *root_path);
 | 
				
			||||||
 | 
					    void MakeSha256HierarchicalContentFilePath_ForFat32KCluster(PathString *out, ContentId content_id, const char *root_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t GetHierarchicalContentDirectoryDepth(MakeContentPathFunction func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void MakeFlatPlaceHolderFilePath(PathString *out, PlaceHolderId placeholder_id, const char *root_path);
 | 
				
			||||||
 | 
					    void MakeSha256HierarchicalPlaceHolderFilePath_ForFat16KCluster(PathString *out, PlaceHolderId placeholder_id, const char *root_pathroot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t GetHierarchicalPlaceHolderDirectoryDepth(MakePlaceHolderPathFunction func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								libstratosphere/include/stratosphere/ncm/ncm_path.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								libstratosphere/include/stratosphere/ncm/ncm_path.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_directory.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/sf/sf_buffer_tags.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct alignas(4) Path : ams::sf::LargeData {
 | 
				
			||||||
 | 
					        char str[fs::EntryNameLengthMax];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr Path Encode(const char *p) {
 | 
				
			||||||
 | 
					            Path path = {};
 | 
				
			||||||
 | 
					            /* Copy C string to path, terminating when a null byte is found. */
 | 
				
			||||||
 | 
					            for (size_t i = 0; i < sizeof(path) - 1; i++) {
 | 
				
			||||||
 | 
					                path.str[i] = p[i];
 | 
				
			||||||
 | 
					                if (p[i] == '\x00') {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return path;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								libstratosphere/include/stratosphere/ncm/ncm_path_string.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								libstratosphere/include/stratosphere/ncm/ncm_path_string.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_directory.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/kvdb/kvdb_bounded_string.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using PathString = kvdb::BoundedString<fs::EntryNameLengthMax>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct alignas(8) PlaceHolderId {
 | 
				
			||||||
 | 
					        util::Uuid uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator==(const PlaceHolderId& other) const {
 | 
				
			||||||
 | 
					            return this->uuid == other.uuid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator!=(const PlaceHolderId& other) const {
 | 
				
			||||||
 | 
					            return this->uuid != other.uuid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator==(const util::Uuid& other) const {
 | 
				
			||||||
 | 
					            return this->uuid == other;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool operator!=(const util::Uuid& other) const {
 | 
				
			||||||
 | 
					            return this->uuid != other;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static_assert(alignof(PlaceHolderId) == 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr inline PlaceHolderId InvalidPlaceHolderId = { util::InvalidUuid };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										59
									
								
								libstratosphere/include/stratosphere/ncm/ncm_program_id.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libstratosphere/include/stratosphere/ncm/ncm_program_id.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ProgramId {
 | 
				
			||||||
 | 
					        u64 value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static const ProgramId Invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline explicit operator svc::ProgramId() const {
 | 
				
			||||||
 | 
					            static_assert(sizeof(value) == sizeof(svc::ProgramId));
 | 
				
			||||||
 | 
					            return { this->value };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator==(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value == rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator!=(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value != rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator<(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value < rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator<=(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value <= rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator>(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value > rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr bool operator>=(const ProgramId &lhs, const ProgramId &rhs) {
 | 
				
			||||||
 | 
					        return lhs.value >= rhs.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline constexpr const ProgramId ProgramId::Invalid = {};
 | 
				
			||||||
 | 
					    inline constexpr const ProgramId InvalidProgramId = ProgramId::Invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_program_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_storage_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ProgramLocation {
 | 
				
			||||||
 | 
					        ProgramId program_id;
 | 
				
			||||||
 | 
					        u8 storage_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static constexpr ProgramLocation Make(ProgramId program_id, StorageId storage_id) {
 | 
				
			||||||
 | 
					            return { .program_id = program_id, .storage_id = static_cast<u8>(storage_id), };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(ProgramLocation) == 0x10 && std::is_pod<ProgramLocation>::value);
 | 
				
			||||||
 | 
					    static_assert(sizeof(ProgramLocation) == sizeof(::NcmProgramLocation) && alignof(ProgramLocation) == alignof(::NcmProgramLocation), "ProgramLocation Libnx Compatibility");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								libstratosphere/include/stratosphere/ncm/ncm_rights_id.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								libstratosphere/include/stratosphere/ncm/ncm_rights_id.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <vapours.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/fs/fs_rights_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RightsId {
 | 
				
			||||||
 | 
					        fs::RightsId id;
 | 
				
			||||||
 | 
					        u8 key_generation;
 | 
				
			||||||
 | 
					        u8 reserved[7];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static_assert(sizeof(RightsId) == 0x18);
 | 
				
			||||||
 | 
					    static_assert(std::is_pod<RightsId>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms and conditions of the GNU General Public License,
 | 
				
			||||||
 | 
					 * version 2, as published by the Free Software Foundation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
				
			||||||
 | 
					 * more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <stratosphere/os.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_rights_id.hpp>
 | 
				
			||||||
 | 
					#include <stratosphere/ncm/ncm_content_id.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::ncm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class RightsIdCache {
 | 
				
			||||||
 | 
					        NON_COPYABLE(RightsIdCache);
 | 
				
			||||||
 | 
					        NON_MOVEABLE(RightsIdCache);
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            static constexpr size_t MaxEntries = 0x80;
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            struct Entry {
 | 
				
			||||||
 | 
					                public:
 | 
				
			||||||
 | 
					                    util::Uuid uuid;
 | 
				
			||||||
 | 
					                    ncm::RightsId rights_id;
 | 
				
			||||||
 | 
					                    u64 last_accessed;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            Entry entries[MaxEntries];
 | 
				
			||||||
 | 
					            u64 counter;
 | 
				
			||||||
 | 
					            os::Mutex mutex;
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            RightsIdCache() {
 | 
				
			||||||
 | 
					                this->Invalidate();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Invalidate() {
 | 
				
			||||||
 | 
					                this->counter = 2;
 | 
				
			||||||
 | 
					                for (size_t i = 0; i < MaxEntries; i++) {
 | 
				
			||||||
 | 
					                    this->entries[i].last_accessed = 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void Store(ContentId content_id, ncm::RightsId rights_id) {
 | 
				
			||||||
 | 
					                std::scoped_lock lk(this->mutex);
 | 
				
			||||||
 | 
					                Entry *eviction_candidate = &this->entries[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Find a suitable existing entry to store our new one at. */
 | 
				
			||||||
 | 
					                for (size_t i = 1; i < MaxEntries; i++) {
 | 
				
			||||||
 | 
					                    Entry *entry = &this->entries[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */
 | 
				
			||||||
 | 
					                    if (content_id == entry->uuid || (content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) {
 | 
				
			||||||
 | 
					                        eviction_candidate = entry;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Update the cache. */
 | 
				
			||||||
 | 
					                eviction_candidate->uuid = content_id.uuid;
 | 
				
			||||||
 | 
					                eviction_candidate->rights_id = rights_id;
 | 
				
			||||||
 | 
					                eviction_candidate->last_accessed = this->counter++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool Find(ncm::RightsId *out_rights_id, ContentId content_id) {
 | 
				
			||||||
 | 
					                std::scoped_lock lk(this->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Attempt to locate the content id in the cache. */
 | 
				
			||||||
 | 
					                for (size_t i = 0; i < MaxEntries; i++) {
 | 
				
			||||||
 | 
					                    Entry *entry = &this->entries[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (entry->last_accessed != 1 && content_id == entry->uuid) {
 | 
				
			||||||
 | 
					                        entry->last_accessed = this->counter;
 | 
				
			||||||
 | 
					                        this->counter++;
 | 
				
			||||||
 | 
					                        *out_rights_id = entry->rights_id;
 | 
				
			||||||
 | 
					                        return true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user