From bb26633cceaed2f2b2fee09ef0d1d02922a84439 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 25 Jul 2019 22:53:32 +1000 Subject: [PATCH 01/58] Implement NCM --- stratosphere/Makefile | 2 +- stratosphere/ncm/Makefile | 160 ++++ stratosphere/ncm/ncm.json | 66 ++ stratosphere/ncm/source/impl/lr_manager.cpp | 90 +++ stratosphere/ncm/source/impl/lr_manager.hpp | 33 + .../ncm/source/impl/lr_redirection.cpp | 130 +++ .../ncm/source/impl/lr_redirection.hpp | 78 ++ .../ncm/source/impl/ncm_content_manager.cpp | 695 ++++++++++++++++ .../ncm/source/impl/ncm_content_manager.hpp | 47 ++ .../source/impl/ncm_placeholder_accessor.cpp | 233 ++++++ .../source/impl/ncm_placeholder_accessor.hpp | 76 ++ .../ncm/source/impl/ncm_rights_cache.cpp | 31 + .../ncm/source/impl/ncm_rights_cache.hpp | 44 + .../lr_addoncontentlocationresolver.cpp | 57 ++ .../lr_addoncontentlocationresolver.hpp | 49 ++ .../ncm/source/lr_contentlocationresolver.cpp | 198 +++++ .../ncm/source/lr_contentlocationresolver.hpp | 84 ++ .../ncm/source/lr_ilocationresolver.hpp | 81 ++ .../ncm/source/lr_manager_service.cpp | 38 + .../ncm/source/lr_manager_service.hpp | 50 ++ .../lr_redirectonlylocationresolver.cpp | 174 ++++ .../lr_redirectonlylocationresolver.hpp | 74 ++ .../source/lr_registeredlocationresolver.cpp | 108 +++ .../source/lr_registeredlocationresolver.hpp | 71 ++ stratosphere/ncm/source/lr_types.hpp | 115 +++ .../source/ncm_content_manager_service.cpp | 84 ++ .../source/ncm_content_manager_service.hpp | 77 ++ .../ncm/source/ncm_contentmetadatabase.cpp | 697 ++++++++++++++++ .../ncm/source/ncm_contentmetadatabase.hpp | 120 +++ .../ncm/source/ncm_contentstorage.cpp | 762 ++++++++++++++++++ .../ncm/source/ncm_contentstorage.hpp | 115 +++ stratosphere/ncm/source/ncm_fs.cpp | 302 +++++++ stratosphere/ncm/source/ncm_fs.hpp | 110 +++ .../ncm/source/ncm_icontentmetadatabase.hpp | 97 +++ .../ncm/source/ncm_icontentstorage.hpp | 95 +++ stratosphere/ncm/source/ncm_main.cpp | 83 ++ stratosphere/ncm/source/ncm_make_path.cpp | 93 +++ stratosphere/ncm/source/ncm_make_path.hpp | 33 + stratosphere/ncm/source/ncm_path_utils.cpp | 90 +++ stratosphere/ncm/source/ncm_path_utils.hpp | 54 ++ .../ncm/source/ncm_readonlycontentstorage.cpp | 273 +++++++ .../ncm/source/ncm_readonlycontentstorage.hpp | 91 +++ stratosphere/ncm/source/ncm_types.hpp | 164 ++++ stratosphere/ncm/source/ncm_utils.cpp | 81 ++ stratosphere/ncm/source/ncm_utils.hpp | 32 + 45 files changed, 6236 insertions(+), 1 deletion(-) create mode 100644 stratosphere/ncm/Makefile create mode 100644 stratosphere/ncm/ncm.json create mode 100644 stratosphere/ncm/source/impl/lr_manager.cpp create mode 100644 stratosphere/ncm/source/impl/lr_manager.hpp create mode 100644 stratosphere/ncm/source/impl/lr_redirection.cpp create mode 100644 stratosphere/ncm/source/impl/lr_redirection.hpp create mode 100644 stratosphere/ncm/source/impl/ncm_content_manager.cpp create mode 100644 stratosphere/ncm/source/impl/ncm_content_manager.hpp create mode 100644 stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp create mode 100644 stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp create mode 100644 stratosphere/ncm/source/impl/ncm_rights_cache.cpp create mode 100644 stratosphere/ncm/source/impl/ncm_rights_cache.hpp create mode 100644 stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp create mode 100644 stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp create mode 100644 stratosphere/ncm/source/lr_contentlocationresolver.cpp create mode 100644 stratosphere/ncm/source/lr_contentlocationresolver.hpp create mode 100644 stratosphere/ncm/source/lr_ilocationresolver.hpp create mode 100644 stratosphere/ncm/source/lr_manager_service.cpp create mode 100644 stratosphere/ncm/source/lr_manager_service.hpp create mode 100644 stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp create mode 100644 stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp create mode 100644 stratosphere/ncm/source/lr_registeredlocationresolver.cpp create mode 100644 stratosphere/ncm/source/lr_registeredlocationresolver.hpp create mode 100644 stratosphere/ncm/source/lr_types.hpp create mode 100644 stratosphere/ncm/source/ncm_content_manager_service.cpp create mode 100644 stratosphere/ncm/source/ncm_content_manager_service.hpp create mode 100644 stratosphere/ncm/source/ncm_contentmetadatabase.cpp create mode 100644 stratosphere/ncm/source/ncm_contentmetadatabase.hpp create mode 100644 stratosphere/ncm/source/ncm_contentstorage.cpp create mode 100644 stratosphere/ncm/source/ncm_contentstorage.hpp create mode 100644 stratosphere/ncm/source/ncm_fs.cpp create mode 100644 stratosphere/ncm/source/ncm_fs.hpp create mode 100644 stratosphere/ncm/source/ncm_icontentmetadatabase.hpp create mode 100644 stratosphere/ncm/source/ncm_icontentstorage.hpp create mode 100644 stratosphere/ncm/source/ncm_main.cpp create mode 100644 stratosphere/ncm/source/ncm_make_path.cpp create mode 100644 stratosphere/ncm/source/ncm_make_path.hpp create mode 100644 stratosphere/ncm/source/ncm_path_utils.cpp create mode 100644 stratosphere/ncm/source/ncm_path_utils.hpp create mode 100644 stratosphere/ncm/source/ncm_readonlycontentstorage.cpp create mode 100644 stratosphere/ncm/source/ncm_readonlycontentstorage.hpp create mode 100644 stratosphere/ncm/source/ncm_types.hpp create mode 100644 stratosphere/ncm/source/ncm_utils.cpp create mode 100644 stratosphere/ncm/source/ncm_utils.hpp diff --git a/stratosphere/Makefile b/stratosphere/Makefile index da374f808..8a858beb3 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -MODULES := loader pm sm boot ams_mitm spl eclct.stub ro creport fatal dmnt +MODULES := loader pm sm boot ams_mitm spl eclct.stub ro creport fatal dmnt ncm SUBFOLDERS := libstratosphere $(MODULES) diff --git a/stratosphere/ncm/Makefile b/stratosphere/ncm/Makefile new file mode 100644 index 000000000..9db18530e --- /dev/null +++ b/stratosphere/ncm/Makefile @@ -0,0 +1,160 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source source/impl source/boot2 +DATA := data +INCLUDES := include ../../common/include +EXEFS_SRC := exefs_src + +DEFINES := -DRESULT_ABORT_ON_ASSERT -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lstratosphere -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).kip $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).kip + +$(OUTPUT).kip : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/ncm/ncm.json b/stratosphere/ncm/ncm.json new file mode 100644 index 000000000..247e726c1 --- /dev/null +++ b/stratosphere/ncm/ncm.json @@ -0,0 +1,66 @@ +{ + "name": "NCM", + "title_id": "0x0100000000000002", + "main_thread_stack_size": "0x20000", + "main_thread_priority": 49, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 128 + }, { + "type": "syscalls", + "value": { + "svcSetHeapSize" : "0x01", + "svcSetMemoryPermission" : "0x02", + "svcSetMemoryAttribute" : "0x03", + "svcMapMemory" : "0x04", + "svcUnmapMemory" : "0x05", + "svcQueryMemory" : "0x06", + "svcExitProcess" : "0x07", + "svcCreateThread" : "0x08", + "svcStartThread" : "0x09", + "svcExitThread" : "0x0A", + "svcSleepThread" : "0x0B", + "svcGetThreadPriority" : "0x0C", + "svcSetThreadPriority" : "0x0D", + "svcGetThreadCoreMask" : "0x0E", + "svcSetThreadCoreMask" : "0x0F", + "svcGetCurrentProcessorNumber" : "0x10", + "svcSignalEvent" : "0x11", + "svcClearEvent" : "0x12", + "svcMapSharedMemory" : "0x13", + "svcUnmapSharedMemory" : "0x14", + "svcCreateTransferMemory" : "0x15", + "svcCloseHandle" : "0x16", + "svcResetSignal" : "0x17", + "svcWaitSynchronization" : "0x18", + "svcCancelSynchronization" : "0x19", + "svcArbitrateLock" : "0x1A", + "svcArbitrateUnlock" : "0x1B", + "svcWaitProcessWideKeyAtomic" : "0x1C", + "svcSignalProcessWideKey" : "0x1D", + "svcGetSystemTick" : "0x1E", + "svcConnectToNamedPort" : "0x1F", + "svcSendSyncRequestLight" : "0x20", + "svcSendSyncRequest" : "0x21", + "svcSendSyncRequestWithUserBuffer" : "0x22", + "svcSendAsyncRequestWithUserBuffer" : "0x23", + "svcGetProcessId" : "0x24", + "svcGetThreadId" : "0x25", + "svcBreak" : "0x26", + "svcOutputDebugString" : "0x27", + "svcReturnFromException" : "0x28", + "svcGetInfo" : "0x29", + "svcWaitForAddress" : "0x34", + "svcSignalToAddress" : "0x35", + "svcCreateSession" : "0x40", + "svcAcceptSession" : "0x41", + "svcReplyAndReceiveLight" : "0x42", + "svcReplyAndReceive" : "0x43", + "svcReplyAndReceiveWithUserBuffer" : "0x44" + } + } + ] +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_manager.cpp b/stratosphere/ncm/source/impl/lr_manager.cpp new file mode 100644 index 000000000..2b8134f41 --- /dev/null +++ b/stratosphere/ncm/source/impl/lr_manager.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "../lr_contentlocationresolver.hpp" +#include "../lr_redirectonlylocationresolver.hpp" +#include "lr_manager.hpp" + +namespace sts::lr::impl { + + namespace { + + BoundedMap, 5> g_location_resolvers; + std::shared_ptr g_registered_location_resolver = nullptr; + std::shared_ptr g_add_on_content_location_resolver = nullptr; + HosMutex g_mutex; + + } + + Result OpenLocationResolver(Out> out, ncm::StorageId storage_id) { + std::scoped_lock lk(g_mutex); + auto resolver = g_location_resolvers.Find(storage_id); + + if (!resolver) { + if (storage_id == ncm::StorageId::Host) { + g_location_resolvers[storage_id] = std::make_shared(); + } else { + auto content_resolver = std::make_shared(storage_id); + R_TRY(content_resolver->Refresh()); + g_location_resolvers[storage_id] = std::move(content_resolver); + } + } + + /* Make a copy of the resolver for output. */ + auto tmp_resolver = g_location_resolvers[storage_id]; + out.SetValue(std::move(tmp_resolver)); + return ResultSuccess; + } + + Result OpenRegisteredLocationResolver(Out> out) { + std::scoped_lock lk(g_mutex); + + if (!g_registered_location_resolver) { + g_registered_location_resolver = std::make_shared(); + } + + /* Make a copy of the resolver for output. */ + auto tmp_resolver = g_registered_location_resolver; + out.SetValue(std::move(tmp_resolver)); + return ResultSuccess; + } + + Result RefreshLocationResolver(ncm::StorageId storage_id) { + std::scoped_lock lk(g_mutex); + auto resolver = g_location_resolvers.Find(storage_id); + + if (!resolver) { + return ResultLrUnknownStorageId; + } + + (*resolver)->Refresh(); + return ResultSuccess; + } + + Result OpenAddOnContentLocationResolver(Out> out) { + std::scoped_lock lk(g_mutex); + + if (!g_add_on_content_location_resolver) { + g_add_on_content_location_resolver = std::make_shared(); + } + + /* Make a copy of the resolver for output. */ + auto tmp_resolver = g_add_on_content_location_resolver; + out.SetValue(std::move(tmp_resolver)); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_manager.hpp b/stratosphere/ncm/source/impl/lr_manager.hpp new file mode 100644 index 000000000..c9473b973 --- /dev/null +++ b/stratosphere/ncm/source/impl/lr_manager.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../lr_addoncontentlocationresolver.hpp" +#include "../lr_ilocationresolver.hpp" +#include "../lr_registeredlocationresolver.hpp" + +namespace sts::lr::impl { + + /* Location Resolver API. */ + Result OpenLocationResolver(Out> out, ncm::StorageId storage_id); + Result OpenRegisteredLocationResolver(Out> out); + Result RefreshLocationResolver(ncm::StorageId storage_id); + Result OpenAddOnContentLocationResolver(Out> out); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_redirection.cpp b/stratosphere/ncm/source/impl/lr_redirection.cpp new file mode 100644 index 000000000..240e0f575 --- /dev/null +++ b/stratosphere/ncm/source/impl/lr_redirection.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "lr_redirection.hpp" + +namespace sts::lr::impl { + + bool LocationRedirector::FindRedirection(Path *out, ncm::TitleId title_id) { + if (this->redirection_list.empty()) { + return false; + } + + for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { + if (it->title_id == title_id) { + *out = it->path; + return true; + } + } + + return false; + } + + void LocationRedirector::SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags) { + this->EraseRedirection(title_id); + auto redirection = new LocationRedirection(title_id, path, flags); + this->redirection_list.push_back(*redirection); + } + + void LocationRedirector::SetRedirectionFlags(ncm::TitleId title_id, u32 flags) { + if (!this->redirection_list.empty()) { + for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { + if (it->title_id == title_id) { + it->flags = flags; + break; + } + } + } + } + + void LocationRedirector::EraseRedirection(ncm::TitleId title_id) { + if (!this->redirection_list.empty()) { + for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { + if (it->title_id == title_id) { + auto old = it; + this->redirection_list.erase(old); + delete &(*old); + break; + } + } + } + } + + void LocationRedirector::ClearRedirections(u32 flags) { + for (auto it = this->redirection_list.begin(); it != this->redirection_list.end();) { + if ((it->flags & flags) == flags) { + auto old = it; + it = this->redirection_list.erase(it); + delete &(*old); + } else { + it++; + } + } + } + + bool RegisteredLocationRedirector::FindRedirection(Path *out, ncm::TitleId title_id) { + auto redirection = this->redirections.Find(title_id); + + if (redirection) { + *out = *redirection; + return true; + } + + return false; + } + + bool RegisteredLocationRedirector::SetRedirection(ncm::TitleId title_id, const Path& path) { + if (this->redirections.IsFull()) { + return false; + } + + this->redirections[title_id] = path; + return true; + } + + void RegisteredLocationRedirector::EraseRedirection(ncm::TitleId title_id) { + this->redirections.Remove(title_id); + } + + void RegisteredLocationRedirector::ClearRedirections() { + this->redirections.RemoveAll(); + } + + bool AddOnContentRedirector::FindRedirection(ncm::StorageId *out, ncm::TitleId title_id) { + auto redirection = this->redirections.Find(title_id); + + if (redirection) { + *out = *redirection; + return true; + } + + return false; + } + + Result AddOnContentRedirector::SetRedirection(ncm::TitleId title_id, ncm::StorageId storage_id) { + if (this->redirections.IsFull()) { + return ResultLrTooManyRegisteredPaths; + } + + this->redirections[title_id] = storage_id; + return ResultSuccess; + } + + void AddOnContentRedirector::ClearRedirections() { + this->redirections.RemoveAll(); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp new file mode 100644 index 000000000..b6d346286 --- /dev/null +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../lr_types.hpp" + +namespace sts::lr::impl { + + enum RedirectionFlags { + RedirectionFlags_None = (0 << 0), + RedirectionFlags_Application = (1 << 0), + }; + + class LocationRedirection : public util::IntrusiveListBaseNode { + NON_COPYABLE(LocationRedirection); + NON_MOVEABLE(LocationRedirection); + + public: + ncm::TitleId title_id; + Path path; + u32 flags; + + LocationRedirection(ncm::TitleId title_id, const Path& path, u32 flags) : + title_id(title_id), path(path), flags(flags) { + } + }; + + class LocationRedirector { + NON_COPYABLE(LocationRedirector); + NON_MOVEABLE(LocationRedirector); + private: + sts::util::IntrusiveListBaseTraits::ListType redirection_list; + public: + LocationRedirector() {} + + bool FindRedirection(Path *out, ncm::TitleId title_id); + void SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags = RedirectionFlags_None); + void SetRedirectionFlags(ncm::TitleId title_id, u32 flags); + void EraseRedirection(ncm::TitleId title_id); + void ClearRedirections(u32 flags = RedirectionFlags_None); + }; + + class RegisteredLocationRedirector { + private: + BoundedMap redirections; + public: + bool FindRedirection(Path *out, ncm::TitleId title_id); + bool SetRedirection(ncm::TitleId title_id, const Path& path); + void EraseRedirection(ncm::TitleId title_id); + void ClearRedirections(); + }; + + class AddOnContentRedirector { + private: + BoundedMap redirections; + public: + bool FindRedirection(ncm::StorageId *out, ncm::TitleId title_id); + Result SetRedirection(ncm::TitleId title_id, ncm::StorageId storage_id); + void ClearRedirections(); + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp new file mode 100644 index 000000000..f76e060bc --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include +#include +#include +#include + +#include "../ncm_contentmetadatabase.hpp" +#include "../ncm_contentstorage.hpp" +#include "../ncm_fs.hpp" +#include "../ncm_make_path.hpp" +#include "../ncm_readonlycontentstorage.hpp" +#include "ncm_content_manager.hpp" + +namespace sts::ncm::impl { + + namespace { + + struct ContentStorageEntry { + NON_COPYABLE(ContentStorageEntry); + NON_MOVEABLE(ContentStorageEntry); + + char mount_point[16]; + char root_path[128]; + StorageId storage_id; + FsContentStorageId content_storage_id; + std::shared_ptr content_storage; + + inline ContentStorageEntry() : storage_id(StorageId::None), + content_storage_id(FS_CONTENTSTORAGEID_NandSystem), content_storage(nullptr) { + mount_point[0] = '\0'; + root_path[0] = '\0'; + } + + inline void Initialize(StorageId storage_id, FsContentStorageId content_storage_id) { + this->storage_id = storage_id; + this->content_storage_id = content_storage_id; + this->content_storage = nullptr; + MountName mount_name = CreateUniqueMountName(); + strcpy(this->mount_point, mount_name.name); + snprintf(this->root_path, 0x80, "%s:/", this->mount_point); + } + }; + + struct SaveDataMeta { + u64 id; + u64 size; + u64 journal_size; + u32 flags; + FsSaveDataSpaceId space_id; + } PACKED; + + static_assert(sizeof(SaveDataMeta) == 0x20, "SaveDataMeta definition!"); + + struct ContentMetaDBEntry { + NON_COPYABLE(ContentMetaDBEntry); + NON_MOVEABLE(ContentMetaDBEntry); + + char mount_point[16]; + char meta_path[128]; + StorageId storage_id; + SaveDataMeta save_meta; + std::shared_ptr content_meta_database; + std::optional> kvs; + u32 max_content_metas; + + inline ContentMetaDBEntry() : storage_id(StorageId::None), save_meta({0}), + content_meta_database(nullptr), kvs(std::nullopt), max_content_metas(0) { + mount_point[0] = '\0'; + meta_path[0] = '\0'; + } + + Result Initialize(StorageId storage_id, SaveDataMeta& save_meta, size_t max_content_metas) { + this->storage_id = storage_id; + this->max_content_metas = max_content_metas; + this->save_meta = save_meta; + this->content_meta_database = nullptr; + this->kvs.reset(); + MountName mount_name = CreateUniqueMountName(); + strcpy(this->mount_point, mount_name.name); + this->mount_point[0] = '#'; + snprintf(this->meta_path, 0x80, "%s:/meta", this->mount_point); + return ResultSuccess; + } + + Result InitializeGameCard(size_t max_content_metas) { + this->storage_id = StorageId::GameCard; + this->max_content_metas = max_content_metas; + this->content_meta_database = nullptr; + this->kvs.reset(); + return ResultSuccess; + } + }; + + constexpr size_t MaxContentStorageEntries = 8; + constexpr size_t MaxContentMetaDBEntries = 8; + + HosMutex g_mutex; + bool g_initialized = false; + ContentStorageEntry g_content_storage_entries[MaxContentStorageEntries]; + ContentMetaDBEntry g_content_meta_entries[MaxContentMetaDBEntries]; + u32 g_num_content_storage_entries; + u32 g_num_content_meta_entries; + + ContentStorageEntry* FindContentStorageEntry(StorageId storage_id) { + for (size_t i = 0; i < MaxContentStorageEntries; i++) { + ContentStorageEntry* entry = &g_content_storage_entries[i]; + + if (entry->storage_id == storage_id) { + return entry; + } + } + + return nullptr; + } + + ContentMetaDBEntry* FindContentMetaDBEntry(StorageId storage_id) { + for (size_t i = 0; i < MaxContentMetaDBEntries; i++) { + ContentMetaDBEntry* entry = &g_content_meta_entries[i]; + + if (entry->storage_id == storage_id) { + return entry; + } + } + + return nullptr; + } + + } + + Result InitializeContentManager() { + std::scoped_lock lk(g_mutex); + + /* Already initialized. */ + if (g_initialized) { + return ResultSuccess; + } + + size_t cur_storage_index = g_num_content_storage_entries; + + for (size_t i = 0; i < MaxContentStorageEntries; i++) { + ContentStorageEntry* entry = &g_content_storage_entries[i]; + entry->storage_id = StorageId::None; + } + + for (size_t i = 0; i < MaxContentMetaDBEntries; i++) { + ContentMetaDBEntry* entry = &g_content_meta_entries[i]; + entry->storage_id = StorageId::None; + } + + g_num_content_storage_entries++; + auto storage_entry = &g_content_storage_entries[cur_storage_index]; + + /* First, setup the NandSystem storage entry. */ + storage_entry->Initialize(StorageId::NandSystem, FS_CONTENTSTORAGEID_NandSystem); + + if (R_FAILED(VerifyContentStorage(StorageId::NandSystem))) { + R_TRY(CreateContentStorage(StorageId::NandSystem)); + } + + R_TRY(ActivateContentStorage(StorageId::NandSystem)); + + /* Next, the NandSystem content meta entry. */ + SaveDataMeta nand_system_save_meta; + nand_system_save_meta.id = 0x8000000000000120; + nand_system_save_meta.size = 0x6c000; + nand_system_save_meta.journal_size = 0x6c000; + nand_system_save_meta.flags = FsSaveDataFlags_SurviveFactoryReset| FsSaveDataFlags_SurviveFactoryResetForRefurbishment; + nand_system_save_meta.space_id = FsSaveDataSpaceId_NandSystem; + + size_t cur_meta_index = g_num_content_meta_entries; + g_num_content_meta_entries++; + auto content_meta_entry = &g_content_meta_entries[cur_meta_index]; + + R_TRY(content_meta_entry->Initialize(StorageId::NandSystem, nand_system_save_meta, 0x800)); + + if (R_FAILED(VerifyContentMetaDatabase(StorageId::NandSystem))) { + R_TRY(CreateContentMetaDatabase(StorageId::NandSystem)); + + /* TODO: N supports a number of unused modes here, we don't bother implementing them currently. */ + } + + u32 current_flags = 0; + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200 && R_SUCCEEDED(GetSaveDataFlags(¤t_flags, 0x8000000000000120)) && current_flags != (FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment)) { + SetSaveDataFlags(0x8000000000000120, FsSaveDataSpaceId_NandSystem, FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment); + } + + R_TRY(ActivateContentMetaDatabase(StorageId::NandSystem)); + + /* Now for NandUser's content storage entry. */ + cur_meta_index = g_num_content_meta_entries; + g_num_content_meta_entries++; + storage_entry = &g_content_storage_entries[cur_storage_index]; + storage_entry->Initialize(StorageId::NandUser, FS_CONTENTSTORAGEID_NandUser); + + /* And NandUser's content meta entry. */ + SaveDataMeta nand_user_save_meta; + nand_user_save_meta.id = 0x8000000000000121; + nand_user_save_meta.size = 0x29e000; + nand_user_save_meta.journal_size = 0x29e000; + nand_user_save_meta.flags = 0; + nand_user_save_meta.space_id = FsSaveDataSpaceId_NandSystem; + + cur_meta_index = g_num_content_meta_entries; + g_num_content_meta_entries++; + content_meta_entry = &g_content_meta_entries[cur_meta_index]; + + R_TRY(content_meta_entry->Initialize(StorageId::NandUser, nand_user_save_meta, 0x2000)); + + /* + Beyond this point N no longer appears to bother + incrementing the count for content storage entries or content meta entries. + */ + + /* Next SdCard's content storage entry. */ + g_content_storage_entries[2].Initialize(StorageId::SdCard, FS_CONTENTSTORAGEID_SdCard); + + /* And SdCard's content meta entry. */ + SaveDataMeta sd_card_save_meta; + sd_card_save_meta.id = 0x8000000000000124; + sd_card_save_meta.size = 0xa08000; + sd_card_save_meta.journal_size = 0xa08000; + sd_card_save_meta.flags = 0; + sd_card_save_meta.space_id = FsSaveDataSpaceId_SdCard; + + content_meta_entry = &g_content_meta_entries[2]; + R_TRY(content_meta_entry->Initialize(StorageId::SdCard, sd_card_save_meta, 0x2000)); + + /* GameCard's content storage entry. */ + /* N doesn't set a content storage id for game cards, so we'll just use 0 (NandSystem). */ + g_content_storage_entries[3].Initialize(StorageId::GameCard, FS_CONTENTSTORAGEID_NandSystem); + + /* Lasty, GameCard's content meta entry. */ + content_meta_entry = &g_content_meta_entries[3]; + R_TRY(content_meta_entry->InitializeGameCard(0x800)); + + g_initialized = true; + return ResultSuccess; + } + + void FinalizeContentManager() { + { + std::scoped_lock lk(g_mutex); + + for (size_t i = 0; i < MaxContentStorageEntries; i++) { + ContentStorageEntry* entry = &g_content_storage_entries[i]; + InactivateContentStorage(entry->storage_id); + } + + for (size_t i = 0; i < MaxContentMetaDBEntries; i++) { + ContentMetaDBEntry* entry = &g_content_meta_entries[i]; + InactivateContentMetaDatabase(entry->storage_id); + } + } + + for (size_t i = 0; i < MaxContentMetaDBEntries; i++) { + ContentMetaDBEntry* entry = &g_content_meta_entries[i]; + entry->kvs.reset(); + } + + for (size_t i = 0; i < MaxContentStorageEntries; i++) { + ContentStorageEntry* entry = &g_content_storage_entries[i]; + entry->content_storage = nullptr; + } + } + + Result CreateContentStorage(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + R_TRY(MountContentStorage(entry->mount_point, entry->content_storage_id)); + + ON_SCOPE_EXIT { + Unmount(entry->mount_point); + }; + + R_TRY(EnsureDirectoryRecursively(entry->root_path)); + R_TRY(EnsureContentAndPlaceHolderRoot(entry->root_path)); + + return ResultSuccess; + } + + Result VerifyContentStorage(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + MountName mount_name = CreateUniqueMountName(); + char mount_root[128] = {0}; + strcpy(mount_root, mount_name.name); + strcat(mount_root, strchr(entry->root_path, ':')); + R_TRY(MountContentStorage(mount_name.name, entry->content_storage_id)); + + ON_SCOPE_EXIT { + Unmount(mount_name.name); + }; + + R_TRY(CheckContentStorageDirectoriesExist(mount_root)); + + return ResultSuccess; + } + + Result OpenContentStorage(std::shared_ptr* out, StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + auto content_storage = entry->content_storage; + + if (!content_storage) { + switch (storage_id) { + case StorageId::GameCard: + return ResultNcmGameCardContentStorageNotActive; + + case StorageId::NandSystem: + return ResultNcmNandSystemContentStorageNotActive; + + case StorageId::NandUser: + return ResultNcmNandUserContentStorageNotActive; + + case StorageId::SdCard: + return ResultNcmSdCardContentStorageNotActive; + + default: + return ResultNcmUnknownContentStorageNotActive; + } + } + + *out = std::move(content_storage); + return ResultSuccess; + } + + Result CloseContentStorageForcibly(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + if (!entry->content_storage) { + return ResultSuccess; + } + + /* N doesn't bother checking the result of this */ + entry->content_storage->DisableForcibly(); + Unmount(entry->mount_point); + entry->content_storage = nullptr; + return ResultSuccess; + } + + Result ActivateContentStorage(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + /* Already activated. */ + if (entry->content_storage != nullptr) { + return ResultSuccess; + } + + if (storage_id == StorageId::GameCard) { + FsGameCardHandle gc_hnd; + R_TRY(GetGameCardHandle(&gc_hnd)); + R_TRY(MountGameCardPartition(entry->mount_point, gc_hnd, FsGameCardPartiton_Secure)); + auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + auto content_storage = std::make_shared(); + + R_TRY(content_storage->Initialize(entry->root_path, path::MakeContentPathFlat)); + entry->content_storage = std::move(content_storage); + mount_guard.Cancel(); + } else { + R_TRY(MountContentStorage(entry->mount_point, entry->content_storage_id)); + auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + MakeContentPathFunc content_path_func = nullptr; + MakePlaceHolderPathFunc placeholder_path_func = nullptr; + bool delay_flush = false; + auto content_storage = std::make_shared(); + + switch (storage_id) { + case StorageId::NandSystem: + content_path_func = path::MakeContentPathFlat; + placeholder_path_func = path::MakePlaceHolderPathFlat; + break; + + case StorageId::SdCard: + delay_flush = true; + default: + content_path_func = path::MakeContentPathHashByteLayered; + placeholder_path_func = path::MakePlaceHolderPathHashByteLayered; + break; + } + + R_TRY(content_storage->Initialize(entry->root_path, content_path_func, placeholder_path_func, delay_flush)); + entry->content_storage = std::move(content_storage); + mount_guard.Cancel(); + } + + return ResultSuccess; + } + + Result InactivateContentStorage(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentStorageEntry* entry = FindContentStorageEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + /* Already inactivated. */ + if (entry->content_storage == nullptr) { + return ResultSuccess; + } + + entry->content_storage->DisableForcibly(); + entry->content_storage = nullptr; + Unmount(entry->mount_point); + return ResultSuccess; + } + + Result CreateContentMetaDatabase(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || storage_id == StorageId::GameCard || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + /* N doesn't bother checking the result of this. */ + fsDisableAutoSaveDataCreation(); + + R_TRY_CATCH(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)) { + R_CATCH(ResultFsTargetNotFound) { + R_TRY(fsCreate_SystemSaveData(entry->save_meta.space_id, entry->save_meta.id, entry->save_meta.size, entry->save_meta.journal_size, entry->save_meta.flags)); + R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + } + } R_END_TRY_CATCH; + + ON_SCOPE_EXIT { + Unmount(entry->mount_point); + }; + + R_TRY(EnsureDirectoryRecursively(entry->mount_point)); + R_TRY(fsdevCommitDevice(entry->mount_point)); + + return ResultSuccess; + } + + Result VerifyContentMetaDatabase(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::GameCard) { + return ResultSuccess; + } + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + bool mounted_save_data = false; + + if (!entry->content_meta_database) { + R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + mounted_save_data = true; + } + + bool has_meta_path = false; + R_TRY(HasDirectory(&has_meta_path, entry->meta_path)); + if (!has_meta_path) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (mounted_save_data) { + Unmount(entry->mount_point); + } + + return ResultSuccess; + } + + Result OpenContentMetaDatabase(std::shared_ptr* out, StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + std::shared_ptr content_meta_db = entry->content_meta_database; + + if (!content_meta_db) { + switch (storage_id) { + case StorageId::GameCard: + return ResultNcmGameCardContentMetaDatabaseNotActive; + + case StorageId::NandSystem: + return ResultNcmNandSystemContentMetaDatabaseNotActive; + + case StorageId::NandUser: + return ResultNcmNandUserContentMetaDatabaseNotActive; + + case StorageId::SdCard: + return ResultNcmSdCardContentMetaDatabaseNotActive; + + default: + return ResultNcmUnknownContentMetaDatabaseNotActive; + } + } + + *out = std::move(content_meta_db); + return ResultSuccess; + } + + Result CloseContentMetaDatabaseForcibly(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + std::shared_ptr content_meta_db = entry->content_meta_database; + + if (!content_meta_db) { + return ResultSuccess; + } + + /* N doesn't bother checking the result of this */ + content_meta_db->DisableForcibly(); + + if (storage_id != StorageId::GameCard) { + Unmount(entry->mount_point); + } + + entry->content_meta_database = nullptr; + entry->kvs.reset(); + return ResultSuccess; + } + + Result CleanupContentMetaDatabase(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + if (!entry) { + return ResultNcmUnknownStorage; + } + + R_TRY(fsDeleteSaveDataFileSystemBySaveDataSpaceId(entry->save_meta.space_id, entry->save_meta.id)); + return ResultSuccess; + } + + Result ActivateContentMetaDatabase(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + /* Already activated. */ + if (entry->content_meta_database != nullptr) { + return ResultSuccess; + } + + /* Make a brand new kvs. N doesn't quite do this, but we will for cleanliness. */ + entry->kvs.emplace(); + + if (storage_id != StorageId::GameCard) { + R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + R_TRY(entry->kvs->Initialize(entry->meta_path, entry->max_content_metas)); + R_TRY(entry->kvs->Load()); + + auto content_meta_database = std::make_shared(&*entry->kvs, entry->mount_point); + entry->content_meta_database = std::move(content_meta_database); + mount_guard.Cancel(); + } else { + R_TRY(entry->kvs->Initialize(entry->max_content_metas)); + R_TRY(entry->kvs->Load()); + auto content_meta_database = std::make_shared(&*entry->kvs); + entry->content_meta_database = std::move(content_meta_database); + } + + return ResultSuccess; + } + + Result InactivateContentMetaDatabase(StorageId storage_id) { + std::scoped_lock lk(g_mutex); + + if (storage_id == StorageId::None || static_cast(storage_id) == 6) { + return ResultNcmUnknownStorage; + } + + ContentMetaDBEntry* entry = FindContentMetaDBEntry(storage_id); + + /* Already inactivated. */ + if (entry->content_meta_database == nullptr) { + return ResultSuccess; + } + + entry->content_meta_database->DisableForcibly(); + entry->content_meta_database = nullptr; + /* This should lead to Index's destructor performing cleanup for us. */ + entry->kvs.reset(); + + if (storage_id != StorageId::GameCard) { + Unmount(entry->mount_point); + } + + return ResultSuccess; + } +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.hpp b/stratosphere/ncm/source/impl/ncm_content_manager.hpp new file mode 100644 index 000000000..17423a542 --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_content_manager.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../ncm_icontentmetadatabase.hpp" +#include "../ncm_icontentstorage.hpp" + +namespace sts::ncm::impl { + + /* Initialization/Finalization. */ + Result InitializeContentManager(); + void FinalizeContentManager(); + + /* Content Storage Management. */ + Result CreateContentStorage(StorageId storage_id); + Result VerifyContentStorage(StorageId storage_id); + Result OpenContentStorage(std::shared_ptr* out, StorageId storage_id); + Result CloseContentStorageForcibly(StorageId storage_id); + Result ActivateContentStorage(StorageId storage_id); + Result InactivateContentStorage(StorageId storage_id); + + /* Content Meta Database Management. */ + Result CreateContentMetaDatabase(StorageId storage_id); + Result VerifyContentMetaDatabase(StorageId storage_id); + Result OpenContentMetaDatabase(std::shared_ptr* out, StorageId storage_id); + Result CloseContentMetaDatabaseForcibly(StorageId storage_id); + Result CleanupContentMetaDatabase(StorageId storage_id); + Result ActivateContentMetaDatabase(StorageId storage_id); + Result InactivateContentMetaDatabase(StorageId storage_id); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp new file mode 100644 index 000000000..d03327421 --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_placeholder_accessor.hpp" +#include "../ncm_fs.hpp" +#include "../ncm_utils.hpp" +#include "../ncm_make_path.hpp" +#include "../ncm_path_utils.hpp" + +namespace sts::ncm::impl { + + unsigned int PlaceHolderAccessor::GetDirectoryDepth() { + if (this->make_placeholder_path_func == static_cast(path::MakePlaceHolderPathFlat)) { + return 1; + } else if (this->make_placeholder_path_func == static_cast(path::MakePlaceHolderPathHashByteLayered)) { + return 2; + } + + std::abort(); + } + + void PlaceHolderAccessor::GetPlaceHolderPathUncached(char* placeholder_path_out, PlaceHolderId placeholder_id) { + std::scoped_lock lock(this->cache_mutex); + + if (placeholder_id != InvalidUuid) { + CacheEntry* found_cache = NULL; + + for (size_t i = 0; i < PlaceHolderAccessor::MaxCaches; i++) { + CacheEntry* cache = &this->caches[i]; + + if (placeholder_id == cache->id) { + found_cache = cache; + break; + } + } + + if (found_cache) { + /* Flush and close */ + fsync(fileno(found_cache->handle)); + fclose(found_cache->handle); + std::fill(found_cache->id.uuid, found_cache->id.uuid + sizeof(PlaceHolderId), 0); + } + } + + this->GetPlaceHolderPath(placeholder_path_out, placeholder_id); + } + + Result PlaceHolderAccessor::Create(PlaceHolderId placeholder_id, size_t size) { + char placeholder_path[FS_MAX_PATH] = {0}; + + this->EnsureRecursively(placeholder_id); + this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + + R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { + R_CATCH(ResultFsPathAlreadyExists) { + return ResultNcmPlaceHolderAlreadyExists; + } + } R_END_TRY_CATCH; + + return ResultSuccess; + } + + Result PlaceHolderAccessor::Delete(PlaceHolderId placeholder_id) { + char placeholder_path[FS_MAX_PATH] = {0}; + + this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + + R_TRY_CATCH(fsdevDeleteDirectoryRecursively(placeholder_path)) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + } R_END_TRY_CATCH; + + return ResultSuccess; + } + + Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { + if (this->LoadFromCache(out_handle, placeholder_id)) { + return ResultSuccess; + } + char placeholder_path[FS_MAX_PATH] = {0}; + + this->GetPlaceHolderPath(placeholder_path, placeholder_id); + errno = 0; + *out_handle = fopen(placeholder_path, "w+b"); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result PlaceHolderAccessor::SetSize(PlaceHolderId placeholder_id, size_t size) { + char placeholder_path[FS_MAX_PATH] = {0}; + errno = 0; + this->GetPlaceHolderPath(placeholder_path, placeholder_id); + truncate(placeholder_path, size); + + if (errno != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + } R_END_TRY_CATCH; + } + + return ResultSuccess; + } + + Result PlaceHolderAccessor::GetSize(bool* found_in_cache, size_t* out_size, PlaceHolderId placeholder_id) { + FILE* f = NULL; + + /* Set the scope for the scoped_lock. */ + { + std::scoped_lock lock(this->cache_mutex); + + if (placeholder_id == InvalidUuid) { + *found_in_cache = false; + return ResultSuccess; + } + + CacheEntry* cache_entry = this->FindInCache(placeholder_id); + + if (cache_entry == nullptr) { + *found_in_cache = false; + return ResultSuccess; + } + + cache_entry->id = InvalidUuid; + f = cache_entry->handle; + } + + this->FlushCache(f, placeholder_id); + + errno = 0; + fseek(f, 0L, SEEK_END); + size_t size = ftell(f); + fseek(f, 0L, SEEK_SET); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + *found_in_cache = true; + *out_size = size; + return ResultSuccess; + } + + Result PlaceHolderAccessor::EnsureRecursively(PlaceHolderId placeholder_id) { + char placeholder_path[FS_MAX_PATH] = {0}; + this->GetPlaceHolderPath(placeholder_path, placeholder_id); + R_TRY(EnsureParentDirectoryRecursively(placeholder_path)); + return ResultSuccess; + } + + bool PlaceHolderAccessor::LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id) { + std::scoped_lock lk(this->cache_mutex); + CacheEntry *entry = this->FindInCache(placeholder_id); + if (entry == nullptr) { + return false; + } + entry->id = InvalidUuid; + *out_handle = entry->handle; + return true; + } + + PlaceHolderAccessor::CacheEntry *PlaceHolderAccessor::FindInCache(PlaceHolderId placeholder_id) { + if (placeholder_id == InvalidUuid) { + return nullptr; + } + for (size_t i = 0; i < MaxCaches; i++) { + if (placeholder_id == this->caches[i].id) { + return &this->caches[i]; + } + } + return nullptr; + } + + void PlaceHolderAccessor::FlushCache(FILE* handle, PlaceHolderId placeholder_id) { + std::scoped_lock lk(this->cache_mutex); + CacheEntry* cache = nullptr; + + /* Find an empty cache */ + for (size_t i = 0; i < MaxCaches; i++) { + if (placeholder_id != InvalidUuid) { + cache = &this->caches[i]; + break; + } + } + + /* No empty caches found. Let's clear cache 0. */ + if (cache == nullptr) { + cache = &this->caches[0]; + + /* Flush and close */ + fsync(fileno(cache->handle)); + fclose(cache->handle); + cache->id = InvalidUuid; + } + + cache->id = placeholder_id; + cache->handle = handle; + cache->counter = this->cur_counter; + this->cur_counter++; + } + + void PlaceHolderAccessor::ClearAllCaches() { + for (size_t i = 0; i < MaxCaches; i++) { + CacheEntry* cache = &this->caches[i]; + + if (cache->id != InvalidUuid) { + fsync(fileno(cache->handle)); + fclose(cache->handle); + cache->id = InvalidUuid; + } + } + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp new file mode 100644 index 000000000..1b6e60077 --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../ncm_types.hpp" +#include "../ncm_path_utils.hpp" + +namespace sts::ncm::impl { + + class PlaceHolderAccessor { + public: + class CacheEntry { + public: + PlaceHolderId id; + FILE* handle; + u64 counter; + }; + + public: + static constexpr size_t MaxCaches = 0x2; + + CacheEntry caches[MaxCaches]; + char* root_path; + u64 cur_counter; + HosMutex cache_mutex; + MakePlaceHolderPathFunc make_placeholder_path_func; + bool delay_flush; + + PlaceHolderAccessor() : cur_counter(0), delay_flush(false) { + for (size_t i = 0; i < MaxCaches; i++) { + caches[i].id = InvalidUuid; + } + } + + inline void GetPlaceHolderRootPath(char* out_placeholder_root) { + path::GetPlaceHolderRootPath(out_placeholder_root, this->root_path); + } + + inline void GetPlaceHolderPath(char* out_placeholder_path, PlaceHolderId placeholder_id) { + char placeholder_root_path[FS_MAX_PATH] = {0}; + this->GetPlaceHolderRootPath(placeholder_root_path); + this->make_placeholder_path_func(out_placeholder_path, placeholder_id, placeholder_root_path); + } + + unsigned int GetDirectoryDepth(); + void GetPlaceHolderPathUncached(char* out_placeholder_path, PlaceHolderId placeholder_id); + Result Create(PlaceHolderId placeholder_id, size_t size); + Result Delete(PlaceHolderId placeholder_id); + Result Open(FILE** out_handle, PlaceHolderId placeholder_id); + Result SetSize(PlaceHolderId placeholder_id, size_t size); + Result GetSize(bool* found_in_cache, size_t* out_size, PlaceHolderId placeholder_id); + Result EnsureRecursively(PlaceHolderId placeholder_id); + + CacheEntry *FindInCache(PlaceHolderId placeholder_id); + bool LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id); + void FlushCache(FILE* handle, PlaceHolderId placeholder_id); + void ClearAllCaches(); + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.cpp b/stratosphere/ncm/source/impl/ncm_rights_cache.cpp new file mode 100644 index 000000000..14c314884 --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_rights_cache.hpp" + +namespace sts::ncm::impl { + + namespace { + + RightsIdCache g_rights_id_cache; + + } + + RightsIdCache* GetRightsIdCache() { + return &g_rights_id_cache; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp new file mode 100644 index 000000000..1d09617ca --- /dev/null +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../ncm_types.hpp" + +namespace sts::ncm::impl { + + class RightsIdCache { + public: + static constexpr size_t MaxEntries = 0x80; + public: + struct Entry { + public: + Uuid uuid; + FsRightsId rights_id; + u64 key_generation; + u64 last_accessed = 1; + }; + + Entry entries[MaxEntries]; + u64 counter = 2; + HosMutex mutex; + }; + + RightsIdCache* GetRightsIdCache(); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp new file mode 100644 index 000000000..a6051bdc9 --- /dev/null +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/ncm_content_manager.hpp" +#include "lr_addoncontentlocationresolver.hpp" + +namespace sts::lr { + + AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { + this->redirector.ClearRedirections(); + } + + Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + ncm::StorageId storage_id = ncm::StorageId::None; + + if (!this->redirector.FindRedirection(&storage_id, tid)) { + return ResultLrAddOnContentNotFound; + } + + std::shared_ptr content_meta_database; + std::shared_ptr content_storage; + R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); + R_TRY(ncm::impl::OpenContentStorage(&content_storage, storage_id)); + + ncm::ContentId data_content_id; + R_TRY(content_meta_database->GetLatestData(&data_content_id, tid)); + R_ASSERT(content_storage->GetPath(&path, data_content_id)); + *out.pointer = path; + + return ResultSuccess; + } + + Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { + R_TRY(this->redirector.SetRedirection(tid, storage_id)); + return ResultSuccess; + } + + Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { + this->redirector.ClearRedirections(); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp new file mode 100644 index 000000000..b0d779430 --- /dev/null +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "impl/lr_redirection.hpp" +#include "lr_types.hpp" + +namespace sts::lr { + + class AddOnContentLocationResolverInterface : public IServiceObject { + protected: + enum class CommandId { + ResolveAddOnContentPath = 0, + RegisterAddOnContentStorage = 1, + UnregisterAllAddOnContentPath = 2, + }; + private: + impl::AddOnContentRedirector redirector; + public: + AddOnContentLocationResolverInterface(); + public: + virtual Result ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid); + virtual Result UnregisterAllAddOnContentPath(); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, ResolveAddOnContentPath), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, RegisterAddOnContentStorage), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, UnregisterAllAddOnContentPath), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp new file mode 100644 index 000000000..54e4432ff --- /dev/null +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/ncm_content_manager.hpp" +#include "lr_contentlocationresolver.hpp" + +namespace sts::lr { + + ContentLocationResolverInterface::~ContentLocationResolverInterface() { + this->program_redirector.ClearRedirections(); + this->debug_program_redirector.ClearRedirections(); + this->app_control_redirector.ClearRedirections(); + this->html_docs_redirector.ClearRedirections(); + this->legal_info_redirector.ClearRedirections(); + } + + Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->program_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + ncm::ContentId program_content_id; + + R_TRY_CATCH(this->content_meta_database->GetLatestProgram(&program_content_id, tid)) { + R_CATCH(ResultNcmContentMetaNotFound) { + return ResultLrProgramNotFound; + } + } R_END_TRY_CATCH; + + R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); + *out.pointer = path; + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + this->program_redirector.SetRedirection(tid, *path.pointer); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->app_control_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrControlNotFound; + } + + Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->html_docs_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrHtmlDocumentNotFound; + } + + Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + ncm::ContentId data_content_id; + + R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); + R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); + *out.pointer = path; + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) { + this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->legal_info_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrLegalInformationNotFound; + } + + Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) { + this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::Refresh() { + std::shared_ptr content_meta_database; + std::shared_ptr content_storage; + R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); + R_TRY(ncm::impl::OpenContentStorage(&content_storage, this->storage_id)); + this->content_meta_database = std::move(content_meta_database); + this->content_storage = std::move(content_storage); + + this->program_redirector.ClearRedirections(); + this->debug_program_redirector.ClearRedirections(); + this->app_control_redirector.ClearRedirections(); + this->html_docs_redirector.ClearRedirections(); + this->legal_info_redirector.ClearRedirections(); + + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) { + this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::ClearApplicationRedirection() { + this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + this->program_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + this->app_control_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + this->html_docs_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + this->legal_info_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->debug_program_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + R_TRY_CATCH(this->ResolveProgramPath(&path, tid)) { + R_CATCH(ResultLrProgramNotFound) { + return ResultLrDebugProgramNotFound; + } + } R_END_TRY_CATCH; + + *out.pointer = path; + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) { + this->debug_program_redirector.SetRedirection(tid, *path.pointer); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) { + this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + this->debug_program_redirector.EraseRedirection(tid); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.hpp b/stratosphere/ncm/source/lr_contentlocationresolver.hpp new file mode 100644 index 000000000..aa03d9ad4 --- /dev/null +++ b/stratosphere/ncm/source/lr_contentlocationresolver.hpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "impl/lr_manager.hpp" +#include "lr_ilocationresolver.hpp" +#include "ncm_icontentmetadatabase.hpp" +#include "ncm_icontentstorage.hpp" + +namespace sts::lr { + + class ContentLocationResolverInterface : public ILocationResolver { + private: + ncm::StorageId storage_id; + std::shared_ptr content_meta_database; + std::shared_ptr content_storage; + public: + ContentLocationResolverInterface(ncm::StorageId storage_id) : storage_id(storage_id) { + } + + ~ContentLocationResolverInterface(); + public: + virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) override; + virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) override; + virtual Result Refresh() override; + virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result ClearApplicationRedirection() override; + virtual Result EraseProgramRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) override; + virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveProgramPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectProgramPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveApplicationControlPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveDataPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectApplicationControlPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, Refresh), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectApplicationProgramPath, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ClearApplicationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, EraseProgramRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, EraseApplicationControlRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, EraseApplicationHtmlDocumentRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, EraseApplicationLegalInformationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, ResolveProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, RedirectApplicationProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ContentLocationResolverInterface, EraseProgramRedirectionForDebug, FirmwareVersion_700), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_ilocationresolver.hpp b/stratosphere/ncm/source/lr_ilocationresolver.hpp new file mode 100644 index 000000000..affc57397 --- /dev/null +++ b/stratosphere/ncm/source/lr_ilocationresolver.hpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "impl/lr_redirection.hpp" + +namespace sts::lr { + + class ILocationResolver : public IServiceObject { + protected: + enum class CommandId { + ResolveProgramPath = 0, + RedirectProgramPath = 1, + ResolveApplicationControlPath = 2, + ResolveApplicationHtmlDocumentPath = 3, + ResolveDataPath = 4, + RedirectApplicationControlPath = 5, + RedirectApplicationHtmlDocumentPath = 6, + ResolveApplicationLegalInformationPath = 7, + RedirectApplicationLegalInformationPath = 8, + Refresh = 9, + RedirectApplicationProgramPath = 10, + ClearApplicationRedirection = 11, + EraseProgramRedirection = 12, + EraseApplicationControlRedirection = 13, + EraseApplicationHtmlDocumentRedirection = 14, + EraseApplicationLegalInformationRedirection = 15, + ResolveProgramPathForDebug = 16, + RedirectProgramPathForDebug = 17, + RedirectApplicationProgramPathForDebug = 18, + EraseProgramRedirectionForDebug = 19, + }; + protected: + impl::LocationRedirector program_redirector; + impl::LocationRedirector debug_program_redirector; + impl::LocationRedirector app_control_redirector; + impl::LocationRedirector html_docs_redirector; + impl::LocationRedirector legal_info_redirector; + public: + virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) = 0; + virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) = 0; + virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) = 0; + virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) = 0; + virtual Result Refresh() = 0; + virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) = 0; + virtual Result ClearApplicationRedirection() = 0; + virtual Result EraseProgramRedirection(ncm::TitleId tid) = 0; + virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) = 0; + virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) = 0; + virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) = 0; + virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) = 0; + virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) = 0; + virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) = 0; + virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) = 0; + + public: + DEFINE_SERVICE_DISPATCH_TABLE {}; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp new file mode 100644 index 000000000..b6311dc93 --- /dev/null +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/lr_manager.hpp" +#include "lr_manager_service.hpp" + +namespace sts::lr { + + Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { + return impl::OpenLocationResolver(out, storage_id); + } + + Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { + return impl::OpenRegisteredLocationResolver(out); + } + + Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { + return impl::RefreshLocationResolver(storage_id); + } + + Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { + return impl::OpenAddOnContentLocationResolver(out); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.hpp b/stratosphere/ncm/source/lr_manager_service.hpp new file mode 100644 index 000000000..5a1058346 --- /dev/null +++ b/stratosphere/ncm/source/lr_manager_service.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "lr_addoncontentlocationresolver.hpp" +#include "lr_ilocationresolver.hpp" +#include "lr_registeredlocationresolver.hpp" + +namespace sts::lr { + + class LocationResolverManagerService final : public IServiceObject { + protected: + enum class CommandId { + OpenLocationResolver = 0, + OpenRegisteredLocationResolver = 1, + RefreshLocationResolver = 2, + OpenAddOnContentLocationResolver = 3, + }; + public: + /* Actual commands. */ + virtual Result OpenLocationResolver(Out> out, ncm::StorageId storage_id); + virtual Result OpenRegisteredLocationResolver(Out> out); + virtual Result RefreshLocationResolver(ncm::StorageId storage_id); + virtual Result OpenAddOnContentLocationResolver(Out> out); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(LocationResolverManagerService, OpenLocationResolver), + MAKE_SERVICE_COMMAND_META(LocationResolverManagerService, OpenRegisteredLocationResolver), + MAKE_SERVICE_COMMAND_META(LocationResolverManagerService, RefreshLocationResolver), + MAKE_SERVICE_COMMAND_META(LocationResolverManagerService, OpenAddOnContentLocationResolver, FirmwareVersion_200), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp new file mode 100644 index 000000000..0c4f3242f --- /dev/null +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/ncm_content_manager.hpp" +#include "lr_redirectonlylocationresolver.hpp" + +namespace sts::lr { + + RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { + this->program_redirector.ClearRedirections(); + this->debug_program_redirector.ClearRedirections(); + this->app_control_redirector.ClearRedirections(); + this->html_docs_redirector.ClearRedirections(); + this->legal_info_redirector.ClearRedirections(); + } + + Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->program_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrProgramNotFound; + } + + Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + this->program_redirector.SetRedirection(tid, *path.pointer); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->app_control_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrControlNotFound; + } + + Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->html_docs_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrHtmlDocumentNotFound; + } + + Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + return ResultLrDataNotFound; + } + + Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) { + this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->legal_info_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + return ResultLrLegalInformationNotFound; + } + + Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) { + this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::Refresh() { + this->program_redirector.ClearRedirections(); + this->debug_program_redirector.ClearRedirections(); + this->app_control_redirector.ClearRedirections(); + this->html_docs_redirector.ClearRedirections(); + this->legal_info_redirector.ClearRedirections(); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) { + this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { + this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + this->program_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + this->app_control_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + this->html_docs_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + this->legal_info_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (this->debug_program_redirector.FindRedirection(&path, tid)) { + *out.pointer = path; + return ResultSuccess; + } + + R_TRY_CATCH(this->ResolveProgramPath(&path, tid)) { + R_CATCH(ResultLrProgramNotFound) { + return ResultLrDebugProgramNotFound; + } + } R_END_TRY_CATCH; + + *out.pointer = path; + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) { + this->debug_program_redirector.SetRedirection(tid, *path.pointer); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) { + this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + return ResultSuccess; + } + + Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + this->debug_program_redirector.EraseRedirection(tid); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp new file mode 100644 index 000000000..a963a1de6 --- /dev/null +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "lr_contentlocationresolver.hpp" + +namespace sts::lr { + + class RedirectOnlyLocationResolverInterface : public ILocationResolver { + public: + ~RedirectOnlyLocationResolverInterface(); + public: + virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) override; + virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) override; + virtual Result Refresh() override; + virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result ClearApplicationRedirection() override; + virtual Result EraseProgramRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) override; + virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) override; + virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) override; + virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveProgramPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectProgramPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveApplicationControlPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveDataPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectApplicationControlPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, Refresh), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectApplicationProgramPath, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ClearApplicationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, EraseProgramRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, EraseApplicationControlRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, EraseApplicationHtmlDocumentRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, EraseApplicationLegalInformationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, ResolveProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, RedirectApplicationProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(RedirectOnlyLocationResolverInterface, EraseProgramRedirectionForDebug, FirmwareVersion_700), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp new file mode 100644 index 000000000..384945199 --- /dev/null +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "lr_registeredlocationresolver.hpp" + +namespace sts::lr { + + RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { + this->registered_program_redirector.ClearRedirections(); + this->registered_html_docs_redirector.ClearRedirections(); + } + + RegisteredLocationResolverInterface::~RegisteredLocationResolverInterface() { + /* Ensure entries are deallocated */ + this->html_docs_redirector.ClearRedirections(); + this->program_redirector.ClearRedirections(); + } + + Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (!this->program_redirector.FindRedirection(&path, tid)) { + if (!this->registered_program_redirector.FindRedirection(&path, tid)) { + return ResultLrProgramNotFound; + } + } + + *out.pointer = path; + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::RegisterProgramPath(ncm::TitleId tid, InPointer path) { + Path tmp_path = *path.pointer; + + if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { + this->registered_program_redirector.ClearRedirections(); + this->registered_program_redirector.SetRedirection(tid, tmp_path); + } + + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { + this->registered_program_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + Path tmp_path = *path.pointer; + this->program_redirector.SetRedirection(tid, tmp_path); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + Path path; + + if (!this->html_docs_redirector.FindRedirection(&path, tid)) { + if (!this->registered_html_docs_redirector.FindRedirection(&path, tid)) { + return ResultLrProgramNotFound; + } + } + + *out.pointer = path; + return ResultLrHtmlDocumentNotFound; + } + + Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Path tmp_path = *path.pointer; + + if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { + this->registered_html_docs_redirector.ClearRedirections(); + this->registered_html_docs_redirector.SetRedirection(tid, tmp_path); + } + + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { + this->registered_html_docs_redirector.EraseRedirection(tid); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Path tmp_path = *path.pointer; + this->html_docs_redirector.SetRedirection(tid, tmp_path); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::Refresh() { + this->registered_program_redirector.ClearRedirections(); + this->registered_html_docs_redirector.ClearRedirections(); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp new file mode 100644 index 000000000..8ab09863a --- /dev/null +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "impl/lr_redirection.hpp" +#include "lr_types.hpp" + +namespace sts::lr { + + class RegisteredLocationResolverInterface final : public IServiceObject { + protected: + enum class CommandId { + ResolveProgramPath = 0, + RegisterProgramPath = 1, + UnregisterProgramPath = 2, + RedirectProgramPath = 3, + ResolveHtmlDocumentPath = 4, + RegisterHtmlDocumentPath = 5, + UnregisterHtmlDocumentPath = 6, + RedirectHtmlDocumentPath = 7, + Refresh = 8, + }; + private: + impl::LocationRedirector program_redirector; + impl::RegisteredLocationRedirector registered_program_redirector; + impl::LocationRedirector html_docs_redirector; + impl::RegisteredLocationRedirector registered_html_docs_redirector; + public: + RegisteredLocationResolverInterface(); + ~RegisteredLocationResolverInterface(); + + Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); + Result RegisterProgramPath(ncm::TitleId tid, InPointer path); + Result UnregisterProgramPath(ncm::TitleId tid); + Result RedirectProgramPath(ncm::TitleId tid, InPointer path); + Result ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid); + Result RegisterHtmlDocumentPath(ncm::TitleId tid, InPointer path); + Result UnregisterHtmlDocumentPath(ncm::TitleId tid); + Result RedirectHtmlDocumentPath(ncm::TitleId tid, InPointer path); + Result Refresh(); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, ResolveProgramPath), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterProgramPath), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, UnregisterProgramPath), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectProgramPath), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, ResolveHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, UnregisterHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, Refresh, FirmwareVersion_700), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_types.hpp b/stratosphere/ncm/source/lr_types.hpp new file mode 100644 index 000000000..9d921aa45 --- /dev/null +++ b/stratosphere/ncm/source/lr_types.hpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +namespace sts::lr { + + constexpr size_t MaxPathLen = 0x300; + + struct Path { + char path[MaxPathLen]; + + Path() { + path[0] = '\0'; + } + + Path(const char* path) { + strlcpy(this->path, path, MaxPathLen); + } + + Path& operator=(const Path& other) { + /* N appears to always memcpy paths, so we will too. */ + memcpy(this->path, other.path, MaxPathLen); + this->EnsureNullTerminated(); + return *this; + } + + void EnsureNullTerminated() { + const size_t len = strnlen(this->path, MaxPathLen); + + if (len == MaxPathLen) { + path[MaxPathLen-1] = '\0'; + } + } + }; + + template + class BoundedMap { + private: + std::array, N> keys; + std::array values; + public: + Value *Find(const Key &key) { + for (size_t i = 0; i < N; i++) { + if (this->keys[i] && this->keys[i].value() == key) { + return &this->values[i]; + } + } + return nullptr; + } + + void Remove(const Key &key) { + for (size_t i = 0; i < N; i++) { + if (this->keys[i] && this->keys[i].value() == key) { + this->keys[i].reset(); + } + } + } + + void RemoveAll() { + for (size_t i = 0; i < N; i++) { + this->keys[i].reset(); + } + } + + bool IsFull() { + for (size_t i = 0; i < N; i++) { + if (!this->keys[i]) { + return false; + } + } + + return true; + } + + Value &operator[](const Key &key) { + /* Try to find an existing value. */ + { + Value *value = this->Find(key); + if (value) { + return *value; + } + } + + /* Reference a new value. */ + for (size_t i = 0; i < N; i++) { + if (!this->keys[i]) { + this->keys[i] = key; + return this->values[i]; + } + } + + /* We ran out of space in the map. */ + std::abort(); + } + }; + + static constexpr Result ResultLrDebugProgramNotFound = MAKERESULT(Module_Lr, 10); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp new file mode 100644 index 000000000..2418dbd09 --- /dev/null +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/ncm_content_manager.hpp" +#include "ncm_content_manager_service.hpp" + +namespace sts::ncm { + + ContentManagerService::~ContentManagerService() { + impl::FinalizeContentManager(); + } + + Result ContentManagerService::CreateContentStorage(StorageId storage_id) { + return impl::CreateContentStorage(storage_id); + } + + Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { + return impl::CreateContentMetaDatabase(storage_id); + } + + Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { + return impl::VerifyContentStorage(storage_id); + } + + Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { + return impl::VerifyContentMetaDatabase(storage_id); + } + + Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { + std::shared_ptr content_storage; + R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); + out.SetValue(std::move(content_storage)); + return ResultSuccess; + } + + Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { + std::shared_ptr content_meta_database; + R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); + out.SetValue(std::move(content_meta_database)); + return ResultSuccess; + } + + Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { + return impl::CloseContentStorageForcibly(storage_id); + } + + Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { + return impl::CloseContentMetaDatabaseForcibly(storage_id); + } + + Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { + return impl::CleanupContentMetaDatabase(storage_id); + } + + Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { + return impl::ActivateContentStorage(storage_id); + } + + Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { + return impl::InactivateContentStorage(storage_id); + } + + Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { + return impl::ActivateContentMetaDatabase(storage_id); + } + + Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { + return impl::InactivateContentMetaDatabase(storage_id); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.hpp b/stratosphere/ncm/source/ncm_content_manager_service.hpp new file mode 100644 index 000000000..32e014125 --- /dev/null +++ b/stratosphere/ncm/source/ncm_content_manager_service.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "ncm_icontentmetadatabase.hpp" +#include "ncm_icontentstorage.hpp" + +namespace sts::ncm { + + class ContentManagerService final : public 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, + }; + public: + ~ContentManagerService(); + public: + virtual Result CreateContentStorage(StorageId storage_id); + virtual Result CreateContentMetaDatabase(StorageId storage_id); + virtual Result VerifyContentStorage(StorageId storage_id); + virtual Result VerifyContentMetaDatabase(StorageId storage_id); + virtual Result OpenContentStorage(Out> out, StorageId storage_id); + virtual Result OpenContentMetaDatabase(Out> out, StorageId storage_id); + virtual Result CloseContentStorageForcibly(StorageId storage_id); + virtual Result CloseContentMetaDatabaseForcibly(StorageId storage_id); + virtual Result CleanupContentMetaDatabase(StorageId storage_id); + virtual Result ActivateContentStorage(StorageId storage_id); + virtual Result InactivateContentStorage(StorageId storage_id); + virtual Result ActivateContentMetaDatabase(StorageId storage_id); + virtual Result InactivateContentMetaDatabase(StorageId storage_id); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ContentManagerService, CreateContentStorage), + MAKE_SERVICE_COMMAND_META(ContentManagerService, CreateContentMetaDatabase), + MAKE_SERVICE_COMMAND_META(ContentManagerService, VerifyContentStorage), + MAKE_SERVICE_COMMAND_META(ContentManagerService, VerifyContentMetaDatabase), + MAKE_SERVICE_COMMAND_META(ContentManagerService, OpenContentStorage), + MAKE_SERVICE_COMMAND_META(ContentManagerService, OpenContentMetaDatabase), + MAKE_SERVICE_COMMAND_META(ContentManagerService, CloseContentStorageForcibly, FirmwareVersion_100, FirmwareVersion_100), + MAKE_SERVICE_COMMAND_META(ContentManagerService, CloseContentMetaDatabaseForcibly, FirmwareVersion_100, FirmwareVersion_100), + MAKE_SERVICE_COMMAND_META(ContentManagerService, CleanupContentMetaDatabase), + MAKE_SERVICE_COMMAND_META(ContentManagerService, ActivateContentStorage, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentManagerService, InactivateContentStorage, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentManagerService, ActivateContentMetaDatabase, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentManagerService, InactivateContentMetaDatabase, FirmwareVersion_200), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp new file mode 100644 index 000000000..b544de8e6 --- /dev/null +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_contentmetadatabase.hpp" +#include "ncm_utils.hpp" + +namespace sts::ncm { + + namespace { + + struct InstallContentMetaHeader { + u16 extended_header_size; + u16 content_count; + u16 content_meta_count; + ContentMetaAttribute attributes; + u8 padding; + }; + + static_assert(sizeof(InstallContentMetaHeader) == 0x8, "InstallContentMetaHeader definition!"); + + struct ApplicationMetaExtendedHeader { + TitleId patch_id; + u32 required_system_version; + u32 padding; + }; + + struct PatchMetaExtendedHeader { + TitleId application_id; + u32 required_system_version; + u32 extended_data_size; + u8 reserved[0x8]; + }; + + struct AddOnContentMetaExtendedHeader { + TitleId application_id; + u32 required_application_version; + u32 padding; + }; + + struct SystemUpdateMetaExtendedHeader { + u32 extended_data_size; + }; + + inline const InstallContentMetaHeader* GetValueHeader(const void* value) { + return reinterpret_cast(value); + } + + template + inline const ExtendedHeaderType* GetValueExtendedHeader(const void* value) { + return reinterpret_cast(reinterpret_cast(value) + sizeof(InstallContentMetaHeader)); + } + + inline const ContentInfo* GetValueContentInfos(const void* value) { + return reinterpret_cast(reinterpret_cast(value) + sizeof(InstallContentMetaHeader) + GetValueHeader(value)->extended_header_size); + } + + inline const ContentMetaInfo* GetValueContentMetaInfos(const void* value) { + auto header = GetValueHeader(value); + return reinterpret_cast(reinterpret_cast(GetValueContentInfos(value)) + sizeof(ContentInfo) * header->content_count); + } + + Result GetContentMetaSize(size_t *out, const ContentMetaKey &key, const kvdb::MemoryKeyValueStore *kvs) { + R_TRY_CATCH(kvs->GetValueSize(out, key)) { + R_CATCH(ResultKvdbKeyNotFound) { + return ResultNcmContentMetaNotFound; + } + } R_END_TRY_CATCH; + + return ResultSuccess; + } + + Result GetContentMetaValuePointer(const void **out_value_ptr, size_t *out_size, const ContentMetaKey &key, const kvdb::MemoryKeyValueStore *kvs) { + R_TRY(GetContentMetaSize(out_size, key, kvs)); + R_TRY(kvs->GetValuePointer(out_value_ptr, key)); + return ResultSuccess; + } + + } + + Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + const auto it = this->kvs->lower_bound(key); + if (it == this->kvs->end() || it->GetKey().id != key.id) { + return ResultNcmContentMetaNotFound; + } + + const auto stored_key = it->GetKey(); + const void* value = nullptr; + size_t value_size = 0; + + R_TRY(GetContentMetaValuePointer(&value, &value_size, stored_key, this->kvs)); + const auto header = GetValueHeader(value); + + if (header->content_count == 0) { + return ResultNcmContentNotFound; + } + + const ContentInfo* content_infos = GetValueContentInfos(value); + const ContentInfo* found_content_info = nullptr; + + if (id_offset) { + for (size_t i = 0; i < header->content_count; i++) { + const ContentInfo* content_info = &content_infos[i]; + + if (content_info->content_type == type && content_info->id_offset == *id_offset) { + found_content_info = content_info; + break; + } + } + } else { + const ContentInfo* lowest_id_offset_info = nullptr; + + for (size_t i = 0; i < header->content_count; i++) { + const ContentInfo* content_info = &content_infos[i]; + + if (content_info->content_type == type && (!lowest_id_offset_info || lowest_id_offset_info->id_offset > content_info->id_offset)) { + lowest_id_offset_info = content_info; + } + } + + found_content_info = lowest_id_offset_info; + } + + if (!found_content_info) { + return ResultNcmContentNotFound; + } + + *out = found_content_info->content_id; + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetLatestContentMetaKeyImpl(ContentMetaKey* out_key, TitleId tid) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + ContentMetaKey key = {0}; + key.id = tid; + + if (this->kvs->GetCount() == 0) { + return ResultNcmContentMetaNotFound; + } + + auto entry = this->kvs->lower_bound(key); + if (entry == this->kvs->end()) { + return ResultNcmContentMetaNotFound; + } + + bool found_key = false; + + for (; entry != this->kvs->end(); entry++) { + if (entry->GetKey().id != key.id) { + break; + } + + if (entry->GetKey().install_type != ContentInstallType::Full) { + key = entry->GetKey(); + found_key = true; + } + } + + if (!found_key) { + return ResultNcmContentMetaNotFound; + } + + *out_key = key; + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + R_TRY(this->kvs->Remove(key)); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { + ContentId content_id; + R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); + out_content_id.SetValue(content_id); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) { + if (start_index >> 0x1f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto header = GetValueHeader(value); + const auto content_infos = GetValueContentInfos(value); + size_t entries_written = 0; + + if (out_info.num_elements == 0) { + out_entries_written.SetValue(0); + return ResultSuccess; + } + + for (size_t i = start_index; i < out_info.num_elements; i++) { + /* We have no more entries we can read out. */ + if (header->content_count <= start_index + i) { + break; + } + + out_info[i] = content_infos[i]; + entries_written = i + 1; + } + + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + size_t entries_total = 0; + size_t entries_written = 0; + + /* If there are no entries then we've already successfully listed them all. */ + if (this->kvs->GetCount() == 0) { + out_entries_total.SetValue(entries_total); + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + for (auto entry = this->kvs->begin(); entry != this->kvs->end(); entry++) { + ContentMetaKey key = entry->GetKey(); + + /* Check if this entry matches the given filters. */ + if (!((static_cast(type) == 0 || key.type == type) && (title_id_min <= key.id && key.id <= title_id_max) && (key.install_type == ContentInstallType::Full || key.install_type == install_type))) { + continue; + } + + if (static_cast(application_title_id) != 0) { + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + + /* Each of these types are owned by an application. We need to check if their owner application matches the filter. */ + if (key.type == ContentMetaType::Application || key.type == ContentMetaType::Patch || key.type == ContentMetaType::AddOnContent || key.type == ContentMetaType::Delta) { + TitleId entry_application_tid = key.id; + + switch (key.type) { + case ContentMetaType::Application: + break; + default: + /* The first u64 of all non-application extended headers is the application title id. */ + entry_application_tid = *GetValueExtendedHeader(value); + } + + /* Application tid doesn't match filter, skip this entry. */ + if (entry_application_tid != application_title_id) { + continue; + } + } + } + + /* Write the entry to the output buffer. */ + if (entries_written < out_info.num_elements) { + out_info[entries_written] = key; + entries_written++; + } + + entries_total++; + } + + out_entries_total.SetValue(entries_total); + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + ContentMetaKey key; + R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); + out_key.SetValue(key); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + size_t entries_total = 0; + size_t entries_written = 0; + + /* If there are no entries then we've already successfully listed them all. */ + if (this->kvs->GetCount() == 0) { + out_entries_total.SetValue(entries_total); + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + for (auto entry = this->kvs->begin(); entry != this->kvs->end(); entry++) { + ContentMetaKey key = entry->GetKey(); + + /* Check if this entry matches the given filters. */ + if (!((static_cast(type) == 0 || key.type == type))) { + continue; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + + if (key.type == ContentMetaType::Application || key.type == ContentMetaType::Patch || key.type == ContentMetaType::AddOnContent || key.type == ContentMetaType::Delta) { + TitleId application_tid = key.id; + + switch (key.type) { + case ContentMetaType::Application: + break; + default: + /* The first u64 of all non-application extended headers is the application title id. */ + application_tid = *GetValueExtendedHeader(value); + } + + /* Write the entry to the output buffer. */ + if (entries_written < out_keys.num_elements) { + ApplicationContentMetaKey* out_app_key = &out_keys[entries_written]; + out_app_key->application_title_id = application_tid; + out_app_key->key = key; + entries_written++; + } + + entries_total++; + } + } + + out_entries_total.SetValue(entries_total); + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (this->kvs->GetCount() == 0) { + out.SetValue(false); + return ResultSuccess; + } + + bool has = false; + const auto it = this->kvs->lower_bound(key); + if (it != this->kvs->end()) { + has = it->GetKey() == key; + } + + out.SetValue(has); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (keys.num_elements == 0) { + out.SetValue(true); + return ResultSuccess; + } + + for (size_t i = 0; i < keys.num_elements; i++) { + bool has = false; + R_TRY(this->Has(&has, keys[i])); + + if (!has) { + out.SetValue(false); + return ResultSuccess; + } + } + + out.SetValue(true); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (this->kvs->GetCount() == 0) { + return ResultNcmContentMetaNotFound; + } + + const auto it = this->kvs->lower_bound(key); + if (it == this->kvs->end() || it->GetKey() != key) { + return ResultNcmContentMetaNotFound; + } + + out_size.SetValue(it->GetValueSize()); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { + return ResultNcmInvalidContentMetaKey; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + + /* Required system version is at the same offset for the patch and application extended header. + We use the application header for convenience. */ + const auto ext_header = GetValueExtendedHeader(value); + out_version.SetValue(ext_header->required_system_version); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (key.type != ContentMetaType::Application) { + return ResultNcmInvalidContentMetaKey; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto ext_header = GetValueExtendedHeader(value); + out_patch_id.SetValue(ext_header->patch_id); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::DisableForcibly() { + this->disabled = true; + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (out_orphaned.num_elements < content_ids.num_elements) { + return ResultNcmBufferInsufficient; + } + + /* Default to orphaned for all content ids. */ + if (out_orphaned.num_elements > 0) { + std::fill_n(out_orphaned.buffer, out_orphaned.num_elements, true); + } + + if (this->kvs->GetCount() == 0) { + return ResultSuccess; + } + + for (auto entry = this->kvs->begin(); entry != this->kvs->end(); entry++) { + const auto value = entry->GetValuePointer(); + const auto header = GetValueHeader(value); + + if (header->content_count == 0) { + continue; + } + + if (content_ids.num_elements == 0) { + continue; + } + + const ContentInfo* content_infos = GetValueContentInfos(value); + for (size_t i = 0; i < header->content_count; i++) { + const ContentInfo* content_info = &content_infos[i]; + + /* Check if any of this entry's content infos matches one of the provided content ids. + If they do, then the content id isn't orphaned. */ + for (size_t j = 0; j < content_ids.num_elements; j++) { + const ContentId content_id = content_ids[j]; + + if (content_id == content_info->content_id) { + out_orphaned[j] = false; + break; + } + } + } + } + + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::Commit() { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + R_TRY(this->kvs->Save()); + R_TRY(fsdevCommitDevice(this->mount_name)); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto header = GetValueHeader(value); + const ContentInfo* content_infos = GetValueContentInfos(value); + + if (header->content_count > 0) { + for (size_t i = 0; i < header->content_count; i++) { + const ContentInfo* content_info = &content_infos[i]; + + if (content_id == content_info->content_id) { + out.SetValue(false); + return ResultSuccess; + } + } + } + + out.SetValue(false); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { + if (start_index >> 0x1f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto header = GetValueHeader(value); + const auto content_meta_infos = GetValueContentMetaInfos(value); + size_t entries_written = 0; + + if (out_meta_info.num_elements == 0) { + out_entries_written.SetValue(0); + return ResultSuccess; + } + + for (size_t i = start_index; i < out_meta_info.num_elements; i++) { + /* We have no more entries we can read out. */ + if (header->content_meta_count <= start_index + i) { + break; + } + + out_meta_info[i] = content_meta_infos[i]; + entries_written = i + 1; + } + + out_entries_written.SetValue(entries_written); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto header = GetValueHeader(value); + out_attributes.SetValue(header->attributes); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + if (key.type != ContentMetaType::AddOnContent) { + return ResultNcmInvalidContentMetaKey; + } + + const void* value = nullptr; + size_t value_size = 0; + R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); + const auto ext_header = GetValueExtendedHeader(value); + out_version.SetValue(ext_header->required_application_version); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { + ContentId content_id; + R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); + out_content_id.SetValue(content_id); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { + ContentMetaKey key; + + R_TRY(this->GetLatestContentMetaKey(&key, title_id)); + R_TRY(this->GetContentIdByType(out_content_id, key, ContentType::Program)); + return ResultSuccess; + } + + Result ContentMetaDatabaseInterface::GetLatestData(ContentId* out_content_id, TitleId title_id) { + ContentMetaKey key; + + R_TRY(this->GetLatestContentMetaKey(&key, title_id)); + R_TRY(this->GetContentIdByType(out_content_id, key, ContentType::Data)); + return ResultSuccess; + } + + Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId tid) { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + ContentMetaKey key = {0}; + key.id = tid; + + if (this->kvs->GetCount() == 0) { + return ResultNcmContentMetaNotFound; + } + + auto entry = this->kvs->lower_bound(key); + if (entry == this->kvs->end() || entry->GetKey().id != key.id) { + return ResultNcmContentMetaNotFound; + } + + for (; entry != this->kvs->end(); entry++) { + if (entry->GetKey().id != key.id) { + break; + } + + key = entry->GetKey(); + } + + *out_key = key; + return ResultSuccess; + } + + Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + return ResultNcmInvalidContentMetaDatabase; + } + + Result OnMemoryContentMetaDatabaseInterface::Commit() { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp new file mode 100644 index 000000000..faca1e8f3 --- /dev/null +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "ncm_icontentmetadatabase.hpp" + +namespace sts::ncm { + + class ContentMetaDatabaseInterface : public IContentMetaDatabase { + public: + ContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs, const char* mount_name) : IContentMetaDatabase(kvs, mount_name) { + } + ContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs) : IContentMetaDatabase(kvs) { + } + private: + Result GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset); + Result GetLatestContentMetaKeyImpl(ContentMetaKey* out_key, TitleId tid); + public: + virtual Result Set(ContentMetaKey key, InBuffer value) override; + virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value) override; + virtual Result Remove(ContentMetaKey key) override; + virtual Result GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) override; + virtual Result ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) override; + virtual Result List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) override; + virtual Result GetLatestContentMetaKey(Out out_key, TitleId tid) override; + virtual Result ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) override; + virtual Result Has(Out out, ContentMetaKey key) override; + virtual Result HasAll(Out out, InBuffer keys) override; + virtual Result GetSize(Out out_size, ContentMetaKey key) override; + virtual Result GetRequiredSystemVersion(Out out_version, ContentMetaKey key) override; + virtual Result GetPatchId(Out out_patch_id, ContentMetaKey key) override; + virtual Result DisableForcibly() override; + virtual Result LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) override; + virtual Result Commit() override; + virtual Result HasContent(Out out, ContentMetaKey key, ContentId content_id) override; + virtual Result ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) override; + virtual Result GetAttributes(Out out_attributes, ContentMetaKey key) override; + virtual Result GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) override; + virtual Result GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) override; + + /* APIs. */ + virtual Result GetLatestProgram(ContentId* out_content_id, TitleId title_id) override; + virtual Result GetLatestData(ContentId* out_content_id, TitleId title_id) override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, Set), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, Get), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, Remove), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetContentIdByType), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, ListContentInfo), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, List), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetLatestContentMetaKey), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, ListApplication), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, Has), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, HasAll), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetSize), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetRequiredSystemVersion), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetPatchId), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, DisableForcibly), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, LookupOrphanContent), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, Commit), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, HasContent), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, ListContentMetaInfo), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetAttributes), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetRequiredApplicationVersion, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentMetaDatabaseInterface, GetContentIdByTypeAndIdOffset, FirmwareVersion_500), + }; + }; + + class OnMemoryContentMetaDatabaseInterface : public ContentMetaDatabaseInterface { + public: + OnMemoryContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs) : ContentMetaDatabaseInterface(kvs) { + } + public: + virtual Result GetLatestContentMetaKey(Out out_key, TitleId tid) override; + virtual Result LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) override; + virtual Result Commit() override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, Set), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, Get), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, Remove), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetContentIdByType), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, ListContentInfo), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, List), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetLatestContentMetaKey), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, ListApplication), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, Has), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, HasAll), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetSize), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetRequiredSystemVersion), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetPatchId), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, DisableForcibly), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, LookupOrphanContent), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, Commit), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, HasContent), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, ListContentMetaInfo), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetAttributes), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetRequiredApplicationVersion, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(OnMemoryContentMetaDatabaseInterface, GetContentIdByTypeAndIdOffset, FirmwareVersion_500), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp new file mode 100644 index 000000000..cf399c4a1 --- /dev/null +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -0,0 +1,762 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "impl/ncm_rights_cache.hpp" +#include "ncm_contentstorage.hpp" +#include "ncm_fs.hpp" +#include "ncm_make_path.hpp" +#include "ncm_utils.hpp" + +namespace sts::ncm { + + ContentStorageInterface::~ContentStorageInterface() { + this->Finalize(); + } + + Result ContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + R_TRY(CheckContentStorageDirectoriesExist(root_path)); + const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); + + if (root_path_len >= FS_MAX_PATH-1) { + std::abort(); + } + + strncpy(this->root_path, root_path, FS_MAX_PATH-2); + this->make_content_path_func = *content_path_func; + this->placeholder_accessor.root_path = this->root_path; + this->placeholder_accessor.make_placeholder_path_func = *placeholder_path_func; + this->placeholder_accessor.delay_flush = delay_flush; + return ResultSuccess; + } + + void ContentStorageInterface::Finalize() { + this->ClearContentCache(); + this->placeholder_accessor.ClearAllCaches(); + } + + void ContentStorageInterface::ClearContentCache() { + if (this->cached_content_id != InvalidUuid) { + fclose(this->content_cache_file_handle); + this->cached_content_id = InvalidUuid; + } + } + + unsigned int ContentStorageInterface::GetContentDirectoryDepth() { + if (this->make_content_path_func == static_cast(path::MakeContentPathFlat)) { + return 1; + } else if (this->make_content_path_func == static_cast(path::MakeContentPathHashByteLayered)) { + return 2; + } else if (this->make_content_path_func == static_cast(path::MakeContentPath10BitLayered)) { + return 2; + } else if (this->make_content_path_func == static_cast(path::MakeContentPathDualLayered)) { + return 3; + } + + std::abort(); + } + + Result ContentStorageInterface::OpenCachedContentFile(ContentId content_id) { + if (this->cached_content_id == content_id) { + return ResultSuccess; + } + + this->ClearContentCache(); + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + errno = 0; + this->content_cache_file_handle = fopen(content_path, "rb"); + + if (this->content_cache_file_handle == NULL || errno != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmContentNotFound; + } + } R_END_TRY_CATCH; + } + + this->cached_content_id = content_id; + return ResultSuccess; + } + + Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); + return ResultSuccess; + } + + Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + + R_TRY(EnsureParentDirectoryRecursively(content_path)); + R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); + + return ResultSuccess; + } + + Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + return this->placeholder_accessor.Delete(placeholder_id); + } + + Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + if (this->disabled) + return ResultNcmInvalidContentStorage; + + char placeholder_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPlaceHolderPath(placeholder_path, placeholder_id); + + bool has = false; + R_TRY(HasFile(&has, placeholder_path)); + out.SetValue(has); + + return ResultSuccess; + } + + Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + /* Offset is too large */ + if (offset >> 0x3f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + FILE* f = nullptr; + + R_TRY_CATCH(this->placeholder_accessor.Open(&f, placeholder_id)) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + } R_END_TRY_CATCH; + + errno = 0; + fseek(f, offset, SEEK_SET); + fwrite(data.buffer, sizeof(u8), data.num_elements, f); + + if (this->placeholder_accessor.delay_flush ^ 1) { + fsync(fileno(f)); + } + + this->placeholder_accessor.FlushCache(f, placeholder_id); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + this->ClearContentCache(); + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char placeholder_path[FS_MAX_PATH] = {0}; + char content_path[FS_MAX_PATH] = {0}; + + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->GetContentPath(content_path, content_id); + + errno = 0; + rename(placeholder_path, content_path); + + if (errno != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + R_CATCH(ResultFsPathAlreadyExists) { + return ResultNcmContentAlreadyExists; + } + } R_END_TRY_CATCH; + } + + return ResultSuccess; + } + + Result ContentStorageInterface::Delete(ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + this->ClearContentCache(); + + char content_path[FS_MAX_PATH] = {0}; + + this->GetContentPath(content_path, content_id); + + R_TRY_CATCH(fsdevDeleteDirectoryRecursively(content_path)) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmContentNotFound; + } + } R_END_TRY_CATCH; + + return ResultSuccess; + } + + Result ContentStorageInterface::Has(Out out, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + + bool has = false; + R_TRY(HasFile(&has, content_path)); + out.SetValue(has); + + return ResultSuccess; + } + + Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + *out.pointer = common_path; + return ResultSuccess; + } + + Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char placeholder_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + *out.pointer = common_path; + return ResultSuccess; + } + + Result ContentStorageInterface::CleanupAllPlaceHolder() { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char placeholder_root_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.ClearAllCaches(); + this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + + R_TRY(fsdevDeleteDirectoryRecursively(placeholder_root_path)); + + return ResultSuccess; + } + + Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char placeholder_root_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + const unsigned int dir_depth = this->placeholder_accessor.GetDirectoryDepth(); + size_t entry_count = 0; + + R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + *should_continue = true; + *should_retry_dir_read = false; + + if (dir_entry->d_type == DT_REG) { + if (entry_count > out_buf.num_elements) { + return ResultNcmBufferInsufficient; + } + + PlaceHolderId cur_entry_placeholder_id = {0}; + R_TRY(GetPlaceHolderIdFromDirEntry(&cur_entry_placeholder_id, dir_entry)); + out_buf[entry_count++] = cur_entry_placeholder_id; + } + + return ResultSuccess; + })); + + out_count.SetValue(static_cast(entry_count)); + return ResultSuccess; + } + + Result ContentStorageInterface::GetContentCount(Out out_count) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_root_path[FS_MAX_PATH] = {0}; + this->GetContentRootPath(content_root_path); + const unsigned int dir_depth = this->GetContentDirectoryDepth(); + u32 content_count = 0; + + R_TRY(TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + *should_continue = true; + *should_retry_dir_read = false; + + if (dir_entry->d_type == DT_REG) { + content_count++; + } + + return ResultSuccess; + })); + + out_count.SetValue(content_count); + return ResultSuccess; + } + + Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + if (start_offset >> 0x1f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_root_path[FS_MAX_PATH] = {0}; + this->GetContentRootPath(content_root_path); + const unsigned int dir_depth = this->GetContentDirectoryDepth(); + size_t entry_count = 0; + + R_TRY(TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + *should_retry_dir_read = false; + *should_continue = true; + + if (dir_entry->d_type == DT_REG) { + /* Skip entries until we reach the start offset. */ + if (start_offset > 0) { + start_offset--; + return ResultSuccess; + } + + /* We don't necessarily expect to be able to completely fill the output buffer. */ + if (entry_count > out_buf.num_elements) { + *should_continue = false; + return ResultSuccess; + } + + size_t name_len = strlen(dir_entry->d_name); + std::optional content_id = GetContentIdFromString(dir_entry->d_name, name_len); + + /* Skip to the next entry if the id was invalid. */ + if (!content_id) { + return ResultSuccess; + } + + out_buf[entry_count++] = *content_id; + } + + return ResultSuccess; + })); + + out_count.SetValue(static_cast(entry_count)); + return ResultSuccess; + } + + Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + struct stat st; + + errno = 0; + stat(content_path, &st); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + out_size.SetValue(st.st_size); + return ResultSuccess; + } + + Result ContentStorageInterface::DisableForcibly() { + this->disabled = true; + this->ClearContentCache(); + this->placeholder_accessor.ClearAllCaches(); + return ResultSuccess; + } + + Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char old_content_path[FS_MAX_PATH] = {0}; + char new_content_path[FS_MAX_PATH] = {0}; + char placeholder_path[FS_MAX_PATH] = {0}; + + this->ClearContentCache(); + + /* Ensure the new content path is ready. */ + this->GetContentPath(new_content_path, new_content_id); + R_TRY(EnsureParentDirectoryRecursively(new_content_path)); + + R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + errno = 0; + rename(old_content_path, placeholder_path); + + if (errno != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + R_CATCH(ResultFsPathAlreadyExists) { + return ResultNcmPlaceHolderAlreadyExists; + } + } R_END_TRY_CATCH; + } + + return ResultSuccess; + } + + Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); + return ResultSuccess; + } + + Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + /* Offset is too large */ + if (offset >> 0x3f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + R_TRY(this->OpenCachedContentFile(content_id)); + + errno = 0; + fseek(this->content_cache_file_handle, offset, SEEK_SET); + fread(buf.buffer, buf.num_elements, 1, this->content_cache_file_handle); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + FsRightsId rights_id = {0}; + u8 key_generation = 0; + + char placeholder_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); + + out_rights_id.SetValue(rights_id); + out_key_generation.SetValue(static_cast(key_generation)); + + return ResultSuccess; + } + + Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); + + { + std::scoped_lock lk(rights_id_cache->mutex); + + /* Attempt to locate the content id in the cache. */ + for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) { + impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i]; + + if (entry->last_accessed != 1 && content_id == entry->uuid) { + entry->last_accessed = rights_id_cache->counter; + rights_id_cache->counter++; + out_rights_id.SetValue(entry->rights_id); + out_key_generation.SetValue(entry->key_generation); + return ResultSuccess; + } + } + } + + FsRightsId rights_id = {0}; + u8 key_generation = 0; + char content_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); + + { + std::scoped_lock lk(rights_id_cache->mutex); + impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0]; + + /* Find a suitable existing entry to store our new one at. */ + for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) { + impl::RightsIdCache::Entry* entry = &rights_id_cache->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; + eviction_candidate->rights_id = rights_id; + eviction_candidate->key_generation = key_generation; + eviction_candidate->last_accessed = rights_id_cache->counter; + rights_id_cache->counter++; + + /* Set output. */ + out_rights_id.SetValue(rights_id); + out_key_generation.SetValue(key_generation); + } + + return ResultSuccess; + } + + Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + FILE* f = nullptr; + + /* Offset is too large */ + if (offset >> 0x3f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + bool is_development = false; + + if (R_FAILED(splIsDevelopment(&is_development)) || !is_development) { + std::abort(); + } + + this->ClearContentCache(); + + char content_path[FS_MAX_PATH] = {0}; + this->GetContentPath(content_path, content_id); + + errno = 0; + f = fopen(content_path, "w+b"); + + ON_SCOPE_EXIT { + fclose(f); + }; + + if (f == NULL || errno != 0) { + return fsdevGetLastResult(); + } + + fseek(f, offset, SEEK_SET); + fwrite(data.buffer, sizeof(u8), data.num_elements, f); + fsync(fileno(f)); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { + struct statvfs st = {0}; + errno = 0; + statvfs(this->root_path, &st); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + out_size.SetValue(st.f_bfree); + return ResultSuccess; + } + + Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { + struct statvfs st = {0}; + errno = 0; + statvfs(this->root_path, &st); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + out_size.SetValue(st.f_blocks); + return ResultSuccess; + } + + Result ContentStorageInterface::FlushPlaceHolder() { + this->placeholder_accessor.ClearAllCaches(); + return ResultSuccess; + } + + Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + bool found_in_cache = false; + size_t size = 0; + + R_TRY(this->placeholder_accessor.GetSize(&found_in_cache, &size, placeholder_id)); + + if (found_in_cache) { + out_size.SetValue(size); + return ResultSuccess; + } + + char placeholder_path[FS_MAX_PATH] = {0}; + struct stat st; + + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + errno = 0; + stat(placeholder_path, &st); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + out_size.SetValue(st.st_size); + return ResultSuccess; + } + + Result ContentStorageInterface::RepairInvalidFileAttribute() { + char content_root_path[FS_MAX_PATH] = {0}; + this->GetContentRootPath(content_root_path); + unsigned int dir_depth = this->GetContentDirectoryDepth(); + auto fix_file_attributes = [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + *should_retry_dir_read = false; + *should_continue = true; + + if (dir_entry->d_type == DT_DIR) { + if (path::IsNcaPath(current_path)) { + if (R_SUCCEEDED(fsdevSetArchiveBit(current_path))) { + *should_retry_dir_read = true; + } + } + } + + return ResultSuccess; + }; + + R_TRY(TraverseDirectory(content_root_path, dir_depth, fix_file_attributes)); + + char placeholder_root_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.ClearAllCaches(); + this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + dir_depth = this->placeholder_accessor.GetDirectoryDepth(); + + R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); + + return ResultSuccess; + } + + Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); + + { + std::scoped_lock lk(rights_id_cache->mutex); + + /* Attempt to locate the content id in the cache. */ + for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) { + impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i]; + + if (entry->last_accessed != 1 && cache_content_id == entry->uuid) { + entry->last_accessed = rights_id_cache->counter; + rights_id_cache->counter++; + out_rights_id.SetValue(entry->rights_id); + out_key_generation.SetValue(entry->key_generation); + return ResultSuccess; + } + } + } + + FsRightsId rights_id = {0}; + u8 key_generation = 0; + char placeholder_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); + + { + std::scoped_lock lk(rights_id_cache->mutex); + impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0]; + + /* Find a suitable existing entry to store our new one at. */ + for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) { + impl::RightsIdCache::Entry* entry = &rights_id_cache->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 (cache_content_id == entry->uuid || (cache_content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) { + eviction_candidate = entry; + } + } + + /* Update the cache. */ + eviction_candidate->uuid = cache_content_id; + eviction_candidate->rights_id = rights_id; + eviction_candidate->key_generation = key_generation; + eviction_candidate->last_accessed = rights_id_cache->counter; + rights_id_cache->counter++; + + /* Set output. */ + out_rights_id.SetValue(rights_id); + out_key_generation.SetValue(key_generation); + } + + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.hpp b/stratosphere/ncm/source/ncm_contentstorage.hpp new file mode 100644 index 000000000..df124f9bd --- /dev/null +++ b/stratosphere/ncm/source/ncm_contentstorage.hpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "impl/ncm_placeholder_accessor.hpp" +#include "ncm_icontentstorage.hpp" +#include "ncm_path_utils.hpp" + +namespace sts::ncm { + + class ContentStorageInterface : public IContentStorage { + protected: + impl::PlaceHolderAccessor placeholder_accessor; + ContentId cached_content_id; + FILE* content_cache_file_handle; + public: + ~ContentStorageInterface(); + + Result Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush); + void Finalize(); + private: + void ClearContentCache(); + unsigned int GetContentDirectoryDepth(); + Result OpenCachedContentFile(ContentId content_id); + + inline void GetContentRootPath(char* out_content_root) { + path::GetContentRootPath(out_content_root, this->root_path); + } + + inline void GetContentPath(char* out_content_path, ContentId content_id) { + char content_root_path[FS_MAX_PATH] = {0}; + + this->GetContentRootPath(content_root_path); + this->make_content_path_func(out_content_path, content_id, content_root_path); + } + public: + virtual Result GeneratePlaceHolderId(Out out) override; + virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) override; + virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) override; + virtual Result HasPlaceHolder(Out out, PlaceHolderId placeholder_id) override; + virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) override; + virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) override; + virtual Result Delete(ContentId content_id) override; + virtual Result Has(Out out, ContentId content_id) override; + virtual Result GetPath(OutPointerWithServerSize out, ContentId content_id) override; + virtual Result GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) override; + virtual Result CleanupAllPlaceHolder() override; + virtual Result ListPlaceHolder(Out out_count, OutBuffer out_buf) override; + virtual Result GetContentCount(Out out_count) override; + virtual Result ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) override; + virtual Result GetSizeFromContentId(Out out_size, ContentId content_id) override; + virtual Result DisableForcibly() override; + virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) override; + virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) override; + virtual Result ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) override; + virtual Result GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) override; + virtual Result GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) override; + virtual Result WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) override; + virtual Result GetFreeSpaceSize(Out out_size) override; + virtual Result GetTotalSpaceSize(Out out_size) override; + virtual Result FlushPlaceHolder() override; + virtual Result GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) override; + virtual Result RepairInvalidFileAttribute() override; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, CreatePlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, DeletePlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, HasPlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, WritePlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, Register), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, Delete), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, Has), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetPath), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetPlaceHolderPath), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, CleanupAllPlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, ListPlaceHolder), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetContentCount), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, ListContentId), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetSizeFromContentId), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, DisableForcibly), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, RevertToPlaceHolder, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, SetPlaceHolderSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, ReadContentIdFile, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetRightsIdFromPlaceHolderId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetRightsIdFromContentId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, WriteContentForDebug, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetFreeSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetTotalSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, FlushPlaceHolder, FirmwareVersion_300), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetSizeFromPlaceHolderId, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, RepairInvalidFileAttribute, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(ContentStorageInterface, GetRightsIdFromPlaceHolderIdWithCache, FirmwareVersion_800), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp new file mode 100644 index 000000000..4de2822ad --- /dev/null +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include + +#include "ncm_fs.hpp" +#include "ncm_path_utils.hpp" + +namespace sts::ncm { + + Result HasFile(bool* out, const char* path) { + errno = 0; + struct stat st; + + *out = false; + if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { + *out = true; + } + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result HasDirectory(bool* out, const char* path) { + errno = 0; + struct stat st; + + *out = false; + if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { + *out = true; + } + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result CheckContentStorageDirectoriesExist(const char* root_path) { + char content_root[FS_MAX_PATH] = {0}; + char placeholder_root[FS_MAX_PATH] = {0}; + + errno = 0; + + bool has_root = false; + R_TRY(HasDirectory(&has_root, root_path)); + if (!has_root) { + return ResultNcmStorageRootNotFound; + } + + path::GetContentRootPath(content_root, root_path); + + bool has_content_root = false; + R_TRY(HasDirectory(&has_content_root, content_root)); + if (!has_content_root) { + return ResultNcmStoragePathNotFound; + } + + path::GetPlaceHolderRootPath(placeholder_root, root_path); + + bool has_placeholder_root = false; + R_TRY(HasDirectory(&has_placeholder_root, placeholder_root)); + if (!has_placeholder_root) { + return ResultNcmStoragePathNotFound; + } + + return ResultSuccess; + } + + Result EnsureContentAndPlaceHolderRoot(const char* root_path) { + char content_root[FS_MAX_PATH] = {0}; + char placeholder_root[FS_MAX_PATH] = {0}; + + path::GetContentRootPath(content_root, root_path); + R_TRY(EnsureDirectoryRecursively(content_root)); + path::GetPlaceHolderRootPath(placeholder_root, root_path); + R_TRY(EnsureDirectoryRecursively(placeholder_root)); + + return ResultSuccess; + } + + Result EnsureDirectoryRecursively(const char* dir_path) { + return EnsureRecursively(dir_path, true); + } + + Result EnsureRecursively(const char* path, bool is_dir) { + if (!path) { + return ResultFsNullptrArgument; + } + + size_t path_len = strlen(path); + char working_path_buf[FS_MAX_PATH] = {0}; + + if (path_len + 1 < FS_MAX_PATH) { + strncpy(working_path_buf + 1, path, FS_MAX_PATH-1); + + if (path_len != 0) { + for (size_t i = 0; i < path_len; i++) { + if (i != 0 && working_path_buf[i + 1] == '/' && working_path_buf[i] != ':') { + /* Wipe the errno to prevent cross-contamination */ + errno = 0; + /* Temporarily make the path terminate before the '/' */ + working_path_buf[i + 1] = 0; + mkdir(working_path_buf + 1, S_IRWXU); + + if (errno != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathAlreadyExists) { + /* If the path already exists, that's okay. Anything else is an error. */ + } + } R_END_TRY_CATCH; + } + + /* Restore the path to its former state */ + working_path_buf[i + 1] = '/'; + } + } + } + } else { + return ResultNcmAllocationFailed; + } + + return ResultSuccess; + } + + Result EnsureParentDirectoryRecursively(const char* path) { + return EnsureRecursively(path, false); + } + + Result GetGameCardHandle(FsGameCardHandle* out_handle) { + FsDeviceOperator devop; + R_TRY(fsOpenDeviceOperator(&devop)); + + /* Ensure we close even on early return. */ + ON_SCOPE_EXIT { fsDeviceOperatorClose(&devop); }; + + R_TRY(fsDeviceOperatorGetGameCardHandle(&devop, out_handle)); + return ResultSuccess; + } + + static u32 g_mount_index = 0; + static HosMutex g_mount_index_lock; + + MountName CreateUniqueMountName() { + std::scoped_lock lk(g_mount_index_lock); + MountName mount_name; + g_mount_index++; + snprintf(mount_name.name, sizeof(MountName), "@ncm%08x", g_mount_index); + return mount_name; + } + + Result MountSystemSaveData(const char* mount_point, FsSaveDataSpaceId space_id, u64 save_id) { + if (!mount_point) { + return ResultFsNullptrArgument; + } + + FsSave save = { + .saveID = save_id, + .saveDataType = FsSaveDataType_SystemSaveData, + }; + + FsFileSystem fs; + R_TRY(fsMountSystemSaveData(&fs, space_id, &save)); + + if (fsdevMountDevice(mount_point, fs) == -1) { + std::abort(); + } + + return ResultSuccess; + } + + std::map g_mount_content_storage; + + Result MountContentStorage(const char* mount_point, FsContentStorageId id) { + if (!mount_point) { + return ResultFsNullptrArgument; + } + + FsFileSystem fs; + R_TRY(fsOpenContentStorageFileSystem(&fs, id)); + + if (fsdevMountDevice(mount_point, fs) == -1) { + std::abort(); + } + + g_mount_content_storage[mount_point] = id; + return ResultSuccess; + } + + Result MountGameCardPartition(const char* mount_point, const FsGameCardHandle handle, FsGameCardPartiton partition) { + FsFileSystem fs; + R_TRY(fsOpenGameCardFileSystem(&fs, &handle, partition)); + + if (fsdevMountDevice(mount_point, fs) == -1) { + std::abort(); + } + + return ResultSuccess; + } + + Result Unmount(const char* mount_point) { + if (!mount_point) { + return ResultFsNullptrArgument; + } + + /* Erase any content storage mappings which may potentially exist. */ + g_mount_content_storage.erase(mount_point); + + if (fsdevUnmountDevice(mount_point) == -1) { + std::abort(); + } + + return ResultSuccess; + } + + constexpr const char* SystemContentMountName = "@SystemContent"; + constexpr const char* UserContentMountName = "@UserContent"; + constexpr const char* SdCardContentMountName = "@SdCardContent"; + + Result ConvertToFsCommonPath(char* out_common_path, size_t out_len, const char* path) { + if (!out_common_path || !path) { + return ResultFsNullptrArgument; + } + + MountName mount_name = {0}; + const char* unqual_path = strchr(path, ':'); + + /* We should be given a qualified path. */ + if (!unqual_path || unqual_path > path + 0xf) { + return ResultFsUnqualifiedPath; + } + + strncpy(mount_name.name, path, unqual_path - path); + + if (!fsdevGetDeviceFileSystem(mount_name.name) || g_mount_content_storage.find(mount_name.name) == g_mount_content_storage.end()) { + return ResultFsMountNameNotFound; + } + + FsContentStorageId content_storage_id = g_mount_content_storage[mount_name.name]; + char translated_path[FS_MAX_PATH] = {0}; + const char* common_mount_name; + + switch (content_storage_id) { + case FS_CONTENTSTORAGEID_NandSystem: + common_mount_name = SystemContentMountName; + break; + + case FS_CONTENTSTORAGEID_NandUser: + common_mount_name = UserContentMountName; + break; + + case FS_CONTENTSTORAGEID_SdCard: + common_mount_name = SdCardContentMountName; + break; + + default: + std::abort(); + }; + + if (fsdevTranslatePath(path, NULL, translated_path) == -1) { + std::abort(); + } + + snprintf(out_common_path, out_len, "%s:/%s", common_mount_name, translated_path); + return ResultSuccess; + } + + Result GetSaveDataFlags(u32* out_flags, u64 save_id) { + FsSaveDataExtraData extra_data; + + R_TRY(fsReadSaveDataFileSystemExtraData(&extra_data, sizeof(FsSaveDataExtraData), save_id)); + *out_flags = extra_data.flags; + return ResultSuccess; + } + + Result SetSaveDataFlags(u64 save_id, FsSaveDataSpaceId space_id, u32 flags) { + FsSaveDataExtraData extra_data; + + R_TRY(fsReadSaveDataFileSystemExtraData(&extra_data, sizeof(FsSaveDataExtraData), save_id)); + extra_data.flags = flags; + R_TRY(fsWriteSaveDataFileSystemExtraData(&extra_data, sizeof(FsSaveDataExtraData), space_id, save_id)); + return ResultSuccess; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp new file mode 100644 index 000000000..82cc6c5de --- /dev/null +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +#include "ncm_types.hpp" + +namespace sts::ncm { + + Result HasFile(bool* out, const char* path); + Result HasDirectory(bool* out, const char* path); + + Result CheckContentStorageDirectoriesExist(const char* root_path); + Result EnsureContentAndPlaceHolderRoot(const char* root_path); + + Result EnsureDirectoryRecursively(const char* dir_path); + Result EnsureRecursively(const char* path, bool is_dir); + /* Create all parent directories for a file path */ + Result EnsureParentDirectoryRecursively(const char* path); + + Result GetGameCardHandle(FsGameCardHandle* out_handle); + + MountName CreateUniqueMountName(); + Result MountSystemSaveData(const char* mount_point, FsSaveDataSpaceId space_id, u64 save_id); + Result MountContentStorage(const char* mount_point, FsContentStorageId id); + Result MountGameCardPartition(const char* mount_point, const FsGameCardHandle handle, FsGameCardPartiton partition); + Result Unmount(const char* mount_point); + Result ConvertToFsCommonPath(char* out_common_path, size_t len, const char* path); + + Result GetSaveDataFlags(u32* out_flags, u64 save_id); + Result SetSaveDataFlags(u64 save_id, FsSaveDataSpaceId space_id, u32 flags); + + template + Result TraverseDirectory(const char* root_path, int max_level, F f) { + bool should_continue = false; + return TraverseDirectory(&should_continue, root_path, max_level, f); + } + + template + Result TraverseDirectory(bool* out_should_continue, const char* root_path, int max_level, F f) { + DIR *dir; + struct dirent* dir_entry = nullptr; + if (max_level < 1) { + return ResultSuccess; + } + + bool retry_dir_read = true; + while (retry_dir_read) { + retry_dir_read = false; + + if ((dir = opendir(root_path)) == nullptr) { + return fsdevGetLastResult(); + } + ON_SCOPE_EXIT { closedir(dir); }; + + while ((dir_entry = readdir(dir)) != nullptr) { + if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0) { + continue; + } + + char current_path[FS_MAX_PATH]; + if (snprintf(current_path, FS_MAX_PATH-1, "%s/%s", root_path, dir_entry->d_name) < 0) { + std::abort(); + } + + bool should_continue = true; + bool should_retry_dir_read = false; + R_TRY(f(&should_continue, &should_retry_dir_read, current_path, dir_entry)); + + /* If the provided function wishes to terminate immediately, we should respect it. */ + if (!should_continue) { + *out_should_continue = false; + return ResultSuccess; + } + if (should_retry_dir_read) { + retry_dir_read = true; + break; + } + + if (dir_entry->d_type == DT_DIR) { + R_TRY(TraverseDirectory(&should_continue, current_path, max_level-1, f)); + + if (!should_continue) { + *out_should_continue = false; + return ResultSuccess; + } + } + } + } + + return ResultSuccess; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp new file mode 100644 index 000000000..c094f38f2 --- /dev/null +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +#include "ncm_types.hpp" + +namespace sts::ncm { + + class IContentMetaDatabase : public 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, + }; + protected: + sts::kvdb::MemoryKeyValueStore* kvs; + char mount_name[16]; + bool disabled; + public: + IContentMetaDatabase(sts::kvdb::MemoryKeyValueStore* kvs) : + kvs(kvs), disabled(false) + { + } + + IContentMetaDatabase(sts::kvdb::MemoryKeyValueStore* kvs, const char* mount_name) : + IContentMetaDatabase(kvs) + { + strcpy(this->mount_name, mount_name); + } + public: + /* Actual commands. */ + virtual Result Set(ContentMetaKey key, InBuffer value) = 0; + virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value) = 0; + virtual Result Remove(ContentMetaKey key) = 0; + virtual Result GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) = 0; + virtual Result ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) = 0; + virtual Result List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType meta_type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) = 0; + virtual Result GetLatestContentMetaKey(Out out_key, TitleId tid) = 0; + virtual Result ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType meta_type) = 0; + virtual Result Has(Out out, ContentMetaKey key) = 0; + virtual Result HasAll(Out out, InBuffer keys) = 0; + virtual Result GetSize(Out out_size, ContentMetaKey key) = 0; + virtual Result GetRequiredSystemVersion(Out out_version, ContentMetaKey key) = 0; + virtual Result GetPatchId(Out out_patch_id, ContentMetaKey key) = 0; + virtual Result DisableForcibly() = 0; + virtual Result LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) = 0; + virtual Result Commit() = 0; + virtual Result HasContent(Out out, ContentMetaKey key, ContentId content_id) = 0; + virtual Result ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) = 0; + virtual Result GetAttributes(Out out_attributes, ContentMetaKey key) = 0; + virtual Result GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) = 0; + virtual Result GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) = 0; + + /* APIs. */ + virtual Result GetLatestProgram(ContentId* out_content_id, TitleId title_id) = 0; + virtual Result GetLatestData(ContentId* out_content_id, TitleId title_id) = 0; + public: + DEFINE_SERVICE_DISPATCH_TABLE {}; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp new file mode 100644 index 000000000..a583c937c --- /dev/null +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "lr_types.hpp" +#include "ncm_types.hpp" + +namespace sts::ncm { + + class IContentStorage : public IServiceObject { + 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, + GetRightsIdFromPlaceHolderId = 19, + GetRightsIdFromContentId = 20, + WriteContentForDebug = 21, + GetFreeSpaceSize = 22, + GetTotalSpaceSize = 23, + FlushPlaceHolder = 24, + GetSizeFromPlaceHolderId = 25, + RepairInvalidFileAttribute = 26, + GetRightsIdFromPlaceHolderIdWithCache = 27, + }; + protected: + char root_path[FS_MAX_PATH-1]; + MakeContentPathFunc make_content_path_func; + bool disabled; + public: + virtual Result GeneratePlaceHolderId(Out out) = 0; + virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) = 0; + virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) = 0; + virtual Result HasPlaceHolder(Out out, PlaceHolderId placeholder_id) = 0; + virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) = 0; + virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) = 0; + virtual Result Delete(ContentId content_id) = 0; + virtual Result Has(Out out, ContentId content_id) = 0; + virtual Result GetPath(OutPointerWithServerSize out, ContentId content_id) = 0; + virtual Result GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) = 0; + virtual Result CleanupAllPlaceHolder() = 0; + virtual Result ListPlaceHolder(Out out_count, OutBuffer out_buf) = 0; + virtual Result GetContentCount(Out out_count) = 0; + virtual Result ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) = 0; + virtual Result GetSizeFromContentId(Out 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, u64 size) = 0; + virtual Result ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) = 0; + virtual Result GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) = 0; + virtual Result GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) = 0; + virtual Result WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) = 0; + virtual Result GetFreeSpaceSize(Out out_size) = 0; + virtual Result GetTotalSpaceSize(Out out_size) = 0; + virtual Result FlushPlaceHolder() = 0; + virtual Result GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) = 0; + virtual Result RepairInvalidFileAttribute() = 0; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0; + public: + DEFINE_SERVICE_DISPATCH_TABLE {}; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp new file mode 100644 index 000000000..7779cb992 --- /dev/null +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include +#include + +#include "impl/ncm_content_manager.hpp" +#include "lr_manager_service.hpp" +#include "ncm_content_manager_service.hpp" + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x20000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); + +} + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + SetFirmwareVersionForLibnx(); + + R_ASSERT(smInitialize()); + R_ASSERT(fsInitialize()); +} + +void __appExit(void) { + /* Cleanup services. */ + fsdevUnmountAll(); + fsExit(); + smExit(); +} + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + + auto server_manager = new WaitableManager(2); + + /* Initialize content manager implementation. */ + R_ASSERT(sts::ncm::impl::InitializeContentManager()); + + server_manager->AddWaitable(new ServiceServer("ncm", 0x10)); + server_manager->AddWaitable(new ServiceServer("lr", 0x10)); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; + + return 0; +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_make_path.cpp b/stratosphere/ncm/source/ncm_make_path.cpp new file mode 100644 index 000000000..a4a3ed89d --- /dev/null +++ b/stratosphere/ncm/source/ncm_make_path.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_make_path.hpp" +#include "ncm_path_utils.hpp" + +namespace sts::ncm::path { + + namespace { + + u16 Get16BitSha256HashPrefix(Uuid uuid) { + u8 hash[SHA256_HASH_SIZE]; + sha256CalculateHash(hash, uuid.uuid, sizeof(Uuid)); + return static_cast(hash[0]) | (static_cast(hash[1]) << 8); + } + + u8 Get8BitSha256HashPrefix(Uuid uuid) { + u8 hash[SHA256_HASH_SIZE]; + sha256CalculateHash(hash, uuid.uuid, sizeof(Uuid)); + return hash[0]; + } + + } + + void MakeContentPathFlat(char* path_out, ContentId content_id, const char* root) { + char content_name[FS_MAX_PATH] = {0}; + GetContentFileName(content_name, content_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%s", root, content_name) < 0) { + std::abort(); + } + } + + void MakeContentPathDualLayered(char* path_out, ContentId content_id, const char* root) { + char content_name[FS_MAX_PATH] = {0}; + const u16 hash = Get16BitSha256HashPrefix(content_id); + const u32 hash_lower = (hash >> 4) & 0x3f; + const u32 hash_upper = (hash >> 10) & 0x3f; + + GetContentFileName(content_name, content_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%08X/%s", root, hash_upper, hash_lower, content_name) < 0) { + std::abort(); + } + } + + void MakeContentPath10BitLayered(char* path_out, ContentId content_id, const char* root) { + char content_name[FS_MAX_PATH] = {0}; + const u32 hash = (Get16BitSha256HashPrefix(content_id) >> 6) & 0x3FF; + GetContentFileName(content_name, content_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash, content_name) < 0) { + std::abort(); + } + } + + void MakeContentPathHashByteLayered(char* path_out, ContentId content_id, const char* root) { + char content_name[FS_MAX_PATH] = {0}; + const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(content_id)); + GetContentFileName(content_name, content_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash_byte, content_name) < 0) { + std::abort(); + } + } + + void MakePlaceHolderPathFlat(char* path_out, PlaceHolderId placeholder_id, const char* root) { + char placeholder_name[FS_MAX_PATH] = {0}; + GetPlaceHolderFileName(placeholder_name, placeholder_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%s", root, placeholder_name) < 0) { + std::abort(); + } + } + + void MakePlaceHolderPathHashByteLayered(char* path_out, PlaceHolderId placeholder_id, const char* root) { + char placeholder_name[FS_MAX_PATH] = {0}; + const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(placeholder_id)); + GetPlaceHolderFileName(placeholder_name, placeholder_id); + if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash_byte, placeholder_name) < 0) { + std::abort(); + } + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_make_path.hpp b/stratosphere/ncm/source/ncm_make_path.hpp new file mode 100644 index 000000000..2bd60c849 --- /dev/null +++ b/stratosphere/ncm/source/ncm_make_path.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "ncm_types.hpp" + +namespace sts::ncm::path { + + void MakeContentPathFlat(char* out_path, ContentId content_id, const char* root); + void MakeContentPathHashByteLayered(char* out_path, ContentId content_id, const char* root); + void MakeContentPath10BitLayered(char* out_path, ContentId content_id, const char* root); + void MakeContentPathDualLayered(char* out_path, ContentId content_id, const char* root); + + void MakePlaceHolderPathFlat(char* out_path, PlaceHolderId placeholder_id, const char* root); + void MakePlaceHolderPathHashByteLayered(char* out_path, PlaceHolderId placeholder_id, const char* root); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_path_utils.cpp b/stratosphere/ncm/source/ncm_path_utils.cpp new file mode 100644 index 000000000..57c9458c9 --- /dev/null +++ b/stratosphere/ncm/source/ncm_path_utils.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_path_utils.hpp" +#include "ncm_utils.hpp" + +namespace sts::ncm::path { + + void GetContentMetaPath(char* out, ContentId content_id, MakeContentPathFunc path_func, const char* root_path) { + char tmp_path[FS_MAX_PATH-1] = {0}; + char content_path[FS_MAX_PATH-1] = {0}; + path_func(content_path, content_id, root_path); + const size_t len = strnlen(content_path, FS_MAX_PATH-1); + const size_t len_no_extension = len - 4; + + if (len_no_extension > len || len_no_extension >= FS_MAX_PATH-1) { + std::abort(); + } + + strncpy(tmp_path, content_path, len_no_extension); + memcpy(out, tmp_path, FS_MAX_PATH-1); + const size_t out_len = strnlen(out, FS_MAX_PATH-1); + + if (out_len + 9 >= FS_MAX_PATH-1) { + std::abort(); + } + + strncat(out, ".cnmt.nca", 0x2ff - out_len); + } + + void GetContentFileName(char* out, ContentId content_id) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, content_id); + snprintf(out, FS_MAX_PATH-1, "%s%s", content_name, ".nca"); + } + + void GetPlaceHolderFileName(char* out, PlaceHolderId placeholder_id) { + char placeholder_name[sizeof(PlaceHolderId)*2+1] = {0}; + GetStringFromPlaceHolderId(placeholder_name, placeholder_id); + snprintf(out, FS_MAX_PATH-1, "%s%s", placeholder_name, ".nca"); + } + + bool IsNcaPath(const char* path) { + PathView path_view(path); + + if (!path_view.HasSuffix(".nca")) { + return false; + } + + std::string_view file_name = path_view.GetFileName(); + + if (file_name.length() != 0x24) { + return false; + } + + for (size_t i = 0; i < sizeof(Uuid)*2; i++) { + if (!std::isxdigit(file_name.at(i))) { + return false; + } + } + + return true; + } + + bool PathView::HasPrefix(std::string_view prefix) const { + return this->path.compare(0, prefix.length(), prefix) == 0; + } + + bool PathView::HasSuffix(std::string_view suffix) const { + return this->path.compare(this->path.length() - suffix.length(), suffix.length(), suffix) == 0; + } + + std::string_view PathView::GetFileName() const { + return this->path.substr(this->path.find_last_of("/") + 1); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_path_utils.hpp b/stratosphere/ncm/source/ncm_path_utils.hpp new file mode 100644 index 000000000..cdcd197e0 --- /dev/null +++ b/stratosphere/ncm/source/ncm_path_utils.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "ncm_types.hpp" + +namespace sts::ncm::path { + + inline void GetContentRootPath(char* out_content_root, const char* root_path) { + /* TODO: Replace with BoundedString? */ + if (snprintf(out_content_root, FS_MAX_PATH-1, "%s%s", root_path, "/registered") < 0) { + std::abort(); + } + } + + inline void GetPlaceHolderRootPath(char* out_placeholder_root, const char* root_path) { + /* TODO: Replace with BoundedString? */ + if (snprintf(out_placeholder_root, FS_MAX_PATH, "%s%s", root_path, "/placehld") < 0) { + std::abort(); + } + } + + void GetContentMetaPath(char* out, ContentId content_id, MakeContentPathFunc path_func, const char* root_path); + void GetContentFileName(char* out, ContentId content_id); + void GetPlaceHolderFileName(char* out, PlaceHolderId placeholder_id); + bool IsNcaPath(const char* path); + + class PathView { + private: + std::string_view path; /* Nintendo uses nn::util::string_view here. */ + public: + PathView(std::string_view p) : path(p) { /* ...*/ } + bool HasPrefix(std::string_view prefix) const; + bool HasSuffix(std::string_view suffix) const; + std::string_view GetFileName() const; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp new file mode 100644 index 000000000..ce6a9c985 --- /dev/null +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_fs.hpp" +#include "ncm_path_utils.hpp" +#include "ncm_readonlycontentstorage.hpp" + +namespace sts::ncm { + + Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); + + if (root_path_len >= FS_MAX_PATH-1) { + std::abort(); + } + + strncpy(this->root_path, root_path, FS_MAX_PATH-2); + this->make_content_path_func = *content_path_func; + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + this->make_content_path_func(content_path, content_id, this->root_path); + + bool has = false; + R_TRY(HasFile(&has, content_path)); + + if (!has) { + path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + R_TRY(HasFile(&has, content_path)); + } + + out.SetValue(has); + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + bool is_content_meta_file = false; + + path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + R_TRY(HasFile(&is_content_meta_file, content_path)); + + if (!is_content_meta_file) { + this->make_content_path_func(content_path, content_id, this->root_path); + } + + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + *out.pointer = common_path; + + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + bool is_content_file = false; + + this->make_content_path_func(content_path, content_id, this->root_path); + R_TRY(HasFile(&is_content_file, content_path)); + + if (!is_content_file) { + path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + } + + struct stat st; + errno = 0; + stat(content_path, &st); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + out_size.SetValue(st.st_size); + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::DisableForcibly() { + this->disabled = true; + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + /* Offset is too large */ + if (offset >> 0x3f != 0) { + return ResultNcmInvalidOffset; + } + + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + char content_path[FS_MAX_PATH] = {0}; + bool is_content_file = false; + + this->make_content_path_func(content_path, content_id, this->root_path); + R_TRY(HasFile(&is_content_file, content_path)); + + if (!is_content_file) { + path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + } + + errno = 0; + FILE* f = fopen(content_path, "rb"); + + ON_SCOPE_EXIT { + fclose(f); + }; + + if (f == NULL || errno != 0) { + return fsdevGetLastResult(); + } + + errno = 0; + fseek(f, offset, SEEK_SET); + fread(buf.buffer, buf.num_elements, 1, f); + + if (errno != 0) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + FsRightsId rights_id = {0}; + u8 key_generation = 0; + + char content_path[FS_MAX_PATH] = {0}; + char common_path[FS_MAX_PATH] = {0}; + bool is_content_meta_file = false; + + path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); + R_TRY(HasFile(&is_content_meta_file, content_path)); + + if (!is_content_meta_file) { + this->make_content_path_func(content_path, content_id, this->root_path); + } + + R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); + + out_rights_id.SetValue(rights_id); + out_key_generation.SetValue(static_cast(key_generation)); + + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { + out_size.SetValue(0); + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { + out_size.SetValue(0); + return ResultSuccess; + } + + Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { + return ResultNcmInvalidContentStorageOperation; + } + + Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + return ResultNcmInvalidContentStorageOperation; + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp new file mode 100644 index 000000000..135690230 --- /dev/null +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "ncm_icontentstorage.hpp" + +namespace sts::ncm { + + class ReadOnlyContentStorageInterface : public IContentStorage { + public: + Result Initialize(const char* root_path, MakeContentPathFunc content_path_func); + public: + virtual Result GeneratePlaceHolderId(Out out) override; + virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) override; + virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) override; + virtual Result HasPlaceHolder(Out out, PlaceHolderId placeholder_id) override; + virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) override; + virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) override; + virtual Result Delete(ContentId content_id) override; + virtual Result Has(Out out, ContentId content_id) override; + virtual Result GetPath(OutPointerWithServerSize out, ContentId content_id) override; + virtual Result GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) override; + virtual Result CleanupAllPlaceHolder() override; + virtual Result ListPlaceHolder(Out out_count, OutBuffer out_buf) override; + virtual Result GetContentCount(Out out_count) override; + virtual Result ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) override; + virtual Result GetSizeFromContentId(Out out_size, ContentId content_id) override; + virtual Result DisableForcibly() override; + virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) override; + virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) override; + virtual Result ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) override; + virtual Result GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) override; + virtual Result GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) override; + virtual Result WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) override; + virtual Result GetFreeSpaceSize(Out out_size) override; + virtual Result GetTotalSpaceSize(Out out_size) override; + virtual Result FlushPlaceHolder() override; + virtual Result GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) override; + virtual Result RepairInvalidFileAttribute() override; + virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) override; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, CreatePlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, DeletePlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, HasPlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, WritePlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, Register), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, Delete), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, Has), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetPath), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetPlaceHolderPath), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, CleanupAllPlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, ListPlaceHolder), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetContentCount), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, ListContentId), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetSizeFromContentId), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, DisableForcibly), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, RevertToPlaceHolder, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, SetPlaceHolderSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, ReadContentIdFile, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetRightsIdFromPlaceHolderId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetRightsIdFromContentId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, WriteContentForDebug, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetFreeSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetTotalSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, FlushPlaceHolder, FirmwareVersion_300), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetSizeFromPlaceHolderId, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, RepairInvalidFileAttribute, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(ReadOnlyContentStorageInterface, GetRightsIdFromPlaceHolderIdWithCache, FirmwareVersion_800), + }; + }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp new file mode 100644 index 000000000..98f4a81df --- /dev/null +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +namespace sts::ncm { + + struct MountName { + char name[0x10]; + }; + + struct Uuid { + u8 uuid[0x10]; + + bool operator==(const Uuid& other) const { + return memcmp(this->uuid, other.uuid, sizeof(Uuid)) == 0; + } + + bool operator!=(const Uuid& other) const { + return !(*this == other); + } + }; + + static_assert(sizeof(Uuid) == 0x10, "Uuid definition!"); + + static constexpr Uuid InvalidUuid = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + + typedef Uuid ContentId; + typedef Uuid PlaceHolderId; + + enum class ContentMetaType : u8 { + SystemProgram = 0x1, + SystemData = 0x2, + SystemUpdate = 0x3, + BootImagePackage = 0x4, + BootImagePackageSafe = 0x5, + Application = 0x80, + Patch = 0x81, + AddOnContent = 0x82, + Delta = 0x83, + }; + + enum class ContentType : u8 { + Meta = 0, + Program = 1, + Data = 2, + Control = 3, + HtmlDocument = 4, + LegalInformation = 5, + DeltaFragment = 6, + }; + + enum class ContentMetaAttribute : u8 { + None = 0, + IncludesExFatDriver = 1, + Rebootless = 2, + }; + + enum class ContentInstallType : u8 { + Full = 0, + FragmentOnly = 1, + Unknown = 7, + }; + + struct ContentMetaKey { + TitleId id; + u32 version; + ContentMetaType type; + ContentInstallType install_type; + u8 padding[2]; + + bool operator<(const ContentMetaKey& other) const { + if (this->id < other.id) { + return true; + } else if (this->id != other.id) { + return false; + } + + if (this->version < other.version) { + return true; + } else if (this->version != other.version) { + return false; + } + + if (this->type < other.type) { + return true; + } else if (this->type != other.type) { + return false; + } + + return this->install_type < other.install_type; + } + + bool operator==(const ContentMetaKey& other) const { + if (this->id != other.id) { + return false; + } + + if (this->version != other.version) { + return false; + } + + if (this->type != other.type) { + return false; + } + + if (this->install_type != other.install_type) { + return false; + } + + return true; + } + + bool operator!=(const ContentMetaKey& other) const { + return !(*this == other); + } + } PACKED; + + static_assert(sizeof(ContentMetaKey) == 0x10, "ContentMetaKey definition!"); + + // Used by system updates. They share the exact same struct as ContentMetaKey; + typedef ContentMetaKey ContentMetaInfo; + + struct ApplicationContentMetaKey { + ContentMetaKey key; + TitleId application_title_id; + } PACKED; + + struct ContentInfo { + ContentId content_id; + u8 size[6]; + ContentType content_type; + u8 id_offset; + } PACKED; + + static_assert(sizeof(ContentInfo) == 0x18, "ContentInfo definition!"); + + typedef void (*MakeContentPathFunc)(char* out, ContentId content_id, const char* root); + typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); + + // TODO: Move to libstrat + static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); + static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); + static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); + static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); + static constexpr Result ResultFsUnqualifiedPath = MAKERESULT(Module_Fs, 6065); + static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_utils.cpp b/stratosphere/ncm/source/ncm_utils.cpp new file mode 100644 index 000000000..8be26bf71 --- /dev/null +++ b/stratosphere/ncm/source/ncm_utils.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_utils.hpp" + +namespace sts::ncm { + + void GetStringFromContentId(char* out, ContentId content_id) { + for (size_t i = 0; i < sizeof(ContentId); i++) { + snprintf(out+i, 3, "%02x", content_id.uuid[i]); + } + } + + void GetStringFromPlaceHolderId(char* out, PlaceHolderId placeholder_id) { + for (size_t i = 0; i < sizeof(PlaceHolderId); i++) { + snprintf(out+i, 3, "%02x", placeholder_id.uuid[i]); + } + } + + Result GetPlaceHolderIdFromDirEntry(PlaceHolderId* out, struct dirent* dir_entry) { + if (strnlen(dir_entry->d_name, 0x30) != 0x24 || strncmp(dir_entry->d_name + 0x20, ".nca", 4) != 0) { + return ResultNcmInvalidPlaceHolderDirectoryEntry; + } + + PlaceHolderId placeholder_id = {0}; + char byte_string[2]; + char* end_ptr; + u64 converted_val; + + for (size_t i = 0; i < sizeof(PlaceHolderId); i++) { + char* name_char_pair = dir_entry->d_name + i * 2; + + byte_string[0] = name_char_pair[0]; + byte_string[1] = name_char_pair[1]; + + converted_val = strtoull(byte_string, &end_ptr, 0x10); + placeholder_id.uuid[i] = (u8)converted_val; + } + + *out = placeholder_id; + return ResultSuccess; + } + + std::optional GetContentIdFromString(const char* str, size_t len) { + ContentId content_id = {0}; + + if (len < 0x20) { + return std::nullopt; + } + + char byte_string[2]; + char* end_ptr; + u64 converted_val; + + for (size_t i = 0; i < sizeof(ContentId); i++) { + const char* char_par = str + i * 2; + + byte_string[0] = char_par[0]; + byte_string[1] = char_par[1]; + + converted_val = strtoull(byte_string, &end_ptr, 0x10); + content_id.uuid[i] = (u8)converted_val; + } + + return std::optional(content_id); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_utils.hpp b/stratosphere/ncm/source/ncm_utils.hpp new file mode 100644 index 000000000..20a00662d --- /dev/null +++ b/stratosphere/ncm/source/ncm_utils.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +#include "ncm_types.hpp" + +namespace sts::ncm { + + void GetStringFromContentId(char* out, ContentId content_id); + void GetStringFromPlaceHolderId(char* out, PlaceHolderId placeholder_id); + + Result GetPlaceHolderIdFromDirEntry(PlaceHolderId* out, struct dirent* dir_entry); + std::optional GetContentIdFromString(const char* str, size_t len); + +}; \ No newline at end of file From f5e9f7a8dc60dfaee5cee3dc9db6ed4a51871334 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 26 Jul 2019 08:23:36 +1000 Subject: [PATCH 02/58] Modernize ncm_main --- stratosphere/ncm/source/ncm_main.cpp | 32 +++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 7779cb992..f395c60c4 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include "impl/ncm_content_manager.hpp" @@ -34,6 +35,17 @@ extern "C" { void __appInit(void); void __appExit(void); + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Ncm; + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } void __libnx_initheap(void) { @@ -51,8 +63,11 @@ void __libnx_initheap(void) { void __appInit(void) { SetFirmwareVersionForLibnx(); - R_ASSERT(smInitialize()); - R_ASSERT(fsInitialize()); + DoWithSmSession([&]() { + R_ASSERT(fsInitialize()); + }); + + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { @@ -64,20 +79,17 @@ void __appExit(void) { int main(int argc, char **argv) { - consoleDebugInit(debugDevice_SVC); - - auto server_manager = new WaitableManager(2); + static auto s_server_manager = WaitableManager(2); /* Initialize content manager implementation. */ R_ASSERT(sts::ncm::impl::InitializeContentManager()); - server_manager->AddWaitable(new ServiceServer("ncm", 0x10)); - server_manager->AddWaitable(new ServiceServer("lr", 0x10)); + /* Create services. */ + s_server_manager.AddWaitable(new ServiceServer("ncm", 0x10)); + s_server_manager.AddWaitable(new ServiceServer("lr", 0x10)); /* Loop forever, servicing our services. */ - server_manager->Process(); - - delete server_manager; + s_server_manager.Process(); return 0; } \ No newline at end of file From bc0bfcacfe033901cd3ddfcdf2e8b7a25e1a62b8 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 26 Jul 2019 08:26:18 +1000 Subject: [PATCH 03/58] Remove unnecessary smExit --- stratosphere/ncm/source/ncm_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index f395c60c4..7ab8c5245 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -74,7 +74,6 @@ void __appExit(void) { /* Cleanup services. */ fsdevUnmountAll(); fsExit(); - smExit(); } int main(int argc, char **argv) From 85f74dd7b893bdec49ab1729fff3fbdc673e001e Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 26 Jul 2019 09:04:20 +1000 Subject: [PATCH 04/58] Give access to svcCallSecureMonitor --- stratosphere/ncm/ncm.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stratosphere/ncm/ncm.json b/stratosphere/ncm/ncm.json index 247e726c1..ad491289f 100644 --- a/stratosphere/ncm/ncm.json +++ b/stratosphere/ncm/ncm.json @@ -59,7 +59,8 @@ "svcAcceptSession" : "0x41", "svcReplyAndReceiveLight" : "0x42", "svcReplyAndReceive" : "0x43", - "svcReplyAndReceiveWithUserBuffer" : "0x44" + "svcReplyAndReceiveWithUserBuffer" : "0x44", + "svcCallSecureMonitor" : "0x7F" } } ] From 1cba2985f91038bb42c4e838c5098c3aaee6ec40 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 26 Jul 2019 19:17:43 +1000 Subject: [PATCH 05/58] Stack size bump --- stratosphere/ncm/source/ncm_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 7ab8c5245..361153b9d 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -27,7 +27,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x20000 + #define INNER_HEAP_SIZE 0x60000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; From 1b99cd6b4df2386d478632e6c5e2c95156d1e1c8 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 26 Jul 2019 22:15:18 +1000 Subject: [PATCH 06/58] Fix incorrect setup for NandUser's content storage entry --- stratosphere/ncm/source/impl/ncm_content_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index f76e060bc..9477e1841 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -202,8 +202,8 @@ namespace sts::ncm::impl { R_TRY(ActivateContentMetaDatabase(StorageId::NandSystem)); /* Now for NandUser's content storage entry. */ - cur_meta_index = g_num_content_meta_entries; - g_num_content_meta_entries++; + cur_storage_index = g_num_content_storage_entries; + g_num_content_storage_entries++; storage_entry = &g_content_storage_entries[cur_storage_index]; storage_entry->Initialize(StorageId::NandUser, FS_CONTENTSTORAGEID_NandUser); From 1cd8ac2bb25a0ed72170fbefd815a9e452830afb Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 00:20:56 +1000 Subject: [PATCH 07/58] Fix a potential data abort when flushing the placeholder accessor cache --- .../ncm/source/impl/ncm_placeholder_accessor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index d03327421..e495ee624 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -206,12 +206,15 @@ namespace sts::ncm::impl { if (cache == nullptr) { cache = &this->caches[0]; - /* Flush and close */ - fsync(fileno(cache->handle)); - fclose(cache->handle); + /* Flush and close any handles. */ + if (cache->handle) { + fsync(fileno(cache->handle)); + fclose(cache->handle); + } cache->id = InvalidUuid; } + /* Cache the new placeholder id and its file handle. */ cache->id = placeholder_id; cache->handle = handle; cache->counter = this->cur_counter; From 80d1ec57d103278b056c5f0552af861bb730a1a4 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 01:08:22 +1000 Subject: [PATCH 08/58] Fix HasFile and HasDirectory --- stratosphere/ncm/source/ncm_contentstorage.cpp | 3 ++- stratosphere/ncm/source/ncm_fs.cpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index cf399c4a1..40734f2ab 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -127,8 +127,9 @@ namespace sts::ncm { } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - if (this->disabled) + if (this->disabled) { return ResultNcmInvalidContentStorage; + } char placeholder_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPlaceHolderPath(placeholder_path, placeholder_id); diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 4de2822ad..e9d4aa721 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -25,12 +25,14 @@ namespace sts::ncm { errno = 0; struct stat st; - *out = false; if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { *out = true; + } else { + *out = false; } - if (errno != 0) { + /* It is a valid state for the file to not exist. */ + if (errno != 0 && errno != ENOENT && errno != ENOTDIR) { return fsdevGetLastResult(); } @@ -41,12 +43,14 @@ namespace sts::ncm { errno = 0; struct stat st; - *out = false; if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { *out = true; + } else { + *out = false; } - if (errno != 0) { + /* It is a valid state for the directory to not exist. */ + if (errno != 0 && errno != ENOENT && errno != ENOTDIR) { return fsdevGetLastResult(); } From 070e1012b8ba8570a505c4413fc5b7b7c0d14601 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 01:25:31 +1000 Subject: [PATCH 09/58] Use r+b, not w+b --- stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp | 2 +- stratosphere/ncm/source/ncm_contentstorage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index e495ee624..7f641eb67 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -95,7 +95,7 @@ namespace sts::ncm::impl { this->GetPlaceHolderPath(placeholder_path, placeholder_id); errno = 0; - *out_handle = fopen(placeholder_path, "w+b"); + *out_handle = fopen(placeholder_path, "r+b"); if (errno != 0) { return fsdevGetLastResult(); diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 40734f2ab..08083a00e 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -586,7 +586,7 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); errno = 0; - f = fopen(content_path, "w+b"); + f = fopen(content_path, "r+b"); ON_SCOPE_EXIT { fclose(f); From 65b7ac903904aa280750ff7dac9430016a34aece Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 11:14:39 +1000 Subject: [PATCH 10/58] Misc fixes --- stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp | 8 ++++---- stratosphere/ncm/source/ncm_contentstorage.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 7f641eb67..712420a5e 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -49,7 +49,7 @@ namespace sts::ncm::impl { if (found_cache) { /* Flush and close */ - fsync(fileno(found_cache->handle)); + fflush(found_cache->handle)); fclose(found_cache->handle); std::fill(found_cache->id.uuid, found_cache->id.uuid + sizeof(PlaceHolderId), 0); } @@ -196,7 +196,7 @@ namespace sts::ncm::impl { /* Find an empty cache */ for (size_t i = 0; i < MaxCaches; i++) { - if (placeholder_id != InvalidUuid) { + if (placeholder_id == InvalidUuid) { cache = &this->caches[i]; break; } @@ -208,7 +208,7 @@ namespace sts::ncm::impl { /* Flush and close any handles. */ if (cache->handle) { - fsync(fileno(cache->handle)); + fflush(cache->handle); fclose(cache->handle); } cache->id = InvalidUuid; @@ -226,7 +226,7 @@ namespace sts::ncm::impl { CacheEntry* cache = &this->caches[i]; if (cache->id != InvalidUuid) { - fsync(fileno(cache->handle)); + fflush(cache->handle)); fclose(cache->handle); cache->id = InvalidUuid; } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 08083a00e..1f1da11e7 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -163,8 +163,8 @@ namespace sts::ncm { fseek(f, offset, SEEK_SET); fwrite(data.buffer, sizeof(u8), data.num_elements, f); - if (this->placeholder_accessor.delay_flush ^ 1) { - fsync(fileno(f)); + if (!this->placeholder_accessor.delay_flush) { + fflush(f)); } this->placeholder_accessor.FlushCache(f, placeholder_id); @@ -598,7 +598,7 @@ namespace sts::ncm { fseek(f, offset, SEEK_SET); fwrite(data.buffer, sizeof(u8), data.num_elements, f); - fsync(fileno(f)); + fflush(f)); if (errno != 0) { return fsdevGetLastResult(); From 8f65beef78b83ce6ffe19634ce11127c5e22fa07 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 11:59:56 +1000 Subject: [PATCH 11/58] errno begone --- .../source/impl/ncm_placeholder_accessor.cpp | 28 +++--- .../source/impl/ncm_placeholder_accessor.hpp | 2 +- .../ncm/source/ncm_contentstorage.cpp | 87 +++++++------------ stratosphere/ncm/source/ncm_fs.cpp | 32 +++---- .../ncm/source/ncm_readonlycontentstorage.cpp | 21 ++--- 5 files changed, 65 insertions(+), 105 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 712420a5e..5b6cf5d78 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -49,7 +49,7 @@ namespace sts::ncm::impl { if (found_cache) { /* Flush and close */ - fflush(found_cache->handle)); + fflush(found_cache->handle); fclose(found_cache->handle); std::fill(found_cache->id.uuid, found_cache->id.uuid + sizeof(PlaceHolderId), 0); } @@ -94,23 +94,20 @@ namespace sts::ncm::impl { char placeholder_path[FS_MAX_PATH] = {0}; this->GetPlaceHolderPath(placeholder_path, placeholder_id); - errno = 0; - *out_handle = fopen(placeholder_path, "r+b"); + FILE* f = fopen(placeholder_path, "r+b"); - if (errno != 0) { + if (f == nullptr) { return fsdevGetLastResult(); } + *out_handle = f; return ResultSuccess; } Result PlaceHolderAccessor::SetSize(PlaceHolderId placeholder_id, size_t size) { char placeholder_path[FS_MAX_PATH] = {0}; - errno = 0; this->GetPlaceHolderPath(placeholder_path, placeholder_id); - truncate(placeholder_path, size); - - if (errno != 0) { + if (truncate(placeholder_path, size) == -1) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -144,14 +141,13 @@ namespace sts::ncm::impl { f = cache_entry->handle; } - this->FlushCache(f, placeholder_id); + this->StoreToCache(f, placeholder_id); - errno = 0; - fseek(f, 0L, SEEK_END); + if (!fseek(f, 0L, SEEK_END)) { + return fsdevGetLastResult(); + } size_t size = ftell(f); - fseek(f, 0L, SEEK_SET); - - if (errno != 0) { + if (!fseek(f, 0L, SEEK_SET)) { return fsdevGetLastResult(); } @@ -190,7 +186,7 @@ namespace sts::ncm::impl { return nullptr; } - void PlaceHolderAccessor::FlushCache(FILE* handle, PlaceHolderId placeholder_id) { + void PlaceHolderAccessor::StoreToCache(FILE* handle, PlaceHolderId placeholder_id) { std::scoped_lock lk(this->cache_mutex); CacheEntry* cache = nullptr; @@ -226,7 +222,7 @@ namespace sts::ncm::impl { CacheEntry* cache = &this->caches[i]; if (cache->id != InvalidUuid) { - fflush(cache->handle)); + fflush(cache->handle); fclose(cache->handle); cache->id = InvalidUuid; } diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index 1b6e60077..07ece0506 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -69,7 +69,7 @@ namespace sts::ncm::impl { CacheEntry *FindInCache(PlaceHolderId placeholder_id); bool LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id); - void FlushCache(FILE* handle, PlaceHolderId placeholder_id); + void StoreToCache(FILE* handle, PlaceHolderId placeholder_id); void ClearAllCaches(); }; diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 1f1da11e7..75255d69e 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -80,10 +80,9 @@ namespace sts::ncm { this->ClearContentCache(); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - errno = 0; this->content_cache_file_handle = fopen(content_path, "rb"); - if (this->content_cache_file_handle == NULL || errno != 0) { + if (this->content_cache_file_handle == NULL) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmContentNotFound; @@ -159,20 +158,20 @@ namespace sts::ncm { } } R_END_TRY_CATCH; - errno = 0; - fseek(f, offset, SEEK_SET); - fwrite(data.buffer, sizeof(u8), data.num_elements, f); - - if (!this->placeholder_accessor.delay_flush) { - fflush(f)); - } - - this->placeholder_accessor.FlushCache(f, placeholder_id); - - if (errno != 0) { + if (!fseek(f, offset, SEEK_SET)) { return fsdevGetLastResult(); } + if (fwrite(data.buffer, sizeof(u8), data.num_elements, f) != data.num_elements) { + return fsdevGetLastResult(); + } + + if (!this->placeholder_accessor.delay_flush) { + fflush(f); + } + + this->placeholder_accessor.StoreToCache(f, placeholder_id); + return ResultSuccess; } @@ -189,10 +188,7 @@ namespace sts::ncm { this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); this->GetContentPath(content_path, content_id); - errno = 0; - rename(placeholder_path, content_path); - - if (errno != 0) { + if (!rename(placeholder_path, content_path)) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -395,10 +391,7 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); struct stat st; - errno = 0; - stat(content_path, &st); - - if (errno != 0) { + if (stat(content_path, &st) == -1) { return fsdevGetLastResult(); } @@ -430,10 +423,7 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - errno = 0; - rename(old_content_path, placeholder_path); - - if (errno != 0) { + if (!rename(old_content_path, placeholder_path)) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -442,7 +432,7 @@ namespace sts::ncm { return ResultNcmPlaceHolderAlreadyExists; } } R_END_TRY_CATCH; - } + } return ResultSuccess; } @@ -470,11 +460,11 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(this->OpenCachedContentFile(content_id)); - errno = 0; - fseek(this->content_cache_file_handle, offset, SEEK_SET); - fread(buf.buffer, buf.num_elements, 1, this->content_cache_file_handle); + if (!fseek(this->content_cache_file_handle, offset, SEEK_SET)) { + return fsdevGetLastResult(); + } - if (errno != 0) { + if (fread(buf.buffer, 1, buf.num_elements, this->content_cache_file_handle) != buf.num_elements && ferror(this->content_cache_file_handle)) { return fsdevGetLastResult(); } @@ -563,8 +553,6 @@ namespace sts::ncm { } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - FILE* f = nullptr; - /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -585,34 +573,31 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - errno = 0; - f = fopen(content_path, "r+b"); - + FILE* f = fopen(content_path, "r+b"); ON_SCOPE_EXIT { fclose(f); }; - if (f == NULL || errno != 0) { + if (f == nullptr) { return fsdevGetLastResult(); } - fseek(f, offset, SEEK_SET); - fwrite(data.buffer, sizeof(u8), data.num_elements, f); - fflush(f)); - - if (errno != 0) { + if (!fseek(f, offset, SEEK_SET)) { return fsdevGetLastResult(); } + if (fwrite(data.buffer, sizeof(u8), data.num_elements, f) != data.num_elements) { + return fsdevGetLastResult(); + } + + fflush(f); + return ResultSuccess; } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { struct statvfs st = {0}; - errno = 0; - statvfs(this->root_path, &st); - - if (errno != 0) { + if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } @@ -622,10 +607,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { struct statvfs st = {0}; - errno = 0; - statvfs(this->root_path, &st); - - if (errno != 0) { + if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } @@ -657,11 +639,8 @@ namespace sts::ncm { struct stat st; this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - errno = 0; - stat(placeholder_path, &st); - - if (errno != 0) { - return fsdevGetLastResult(); + if (stat(placeholder_path, &st) == -1) { + return fsdevGetLastResult();; } out_size.SetValue(st.st_size); diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index e9d4aa721..1d1a38e20 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -22,36 +22,32 @@ namespace sts::ncm { Result HasFile(bool* out, const char* path) { - errno = 0; struct stat st; if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { *out = true; } else { - *out = false; - } - - /* It is a valid state for the file to not exist. */ - if (errno != 0 && errno != ENOENT && errno != ENOTDIR) { - return fsdevGetLastResult(); + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + *out = false; + } + } R_END_TRY_CATCH; } return ResultSuccess; } Result HasDirectory(bool* out, const char* path) { - errno = 0; struct stat st; if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { *out = true; } else { - *out = false; - } - - /* It is a valid state for the directory to not exist. */ - if (errno != 0 && errno != ENOENT && errno != ENOTDIR) { - return fsdevGetLastResult(); + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + *out = false; + } + } R_END_TRY_CATCH; } return ResultSuccess; @@ -61,8 +57,6 @@ namespace sts::ncm { char content_root[FS_MAX_PATH] = {0}; char placeholder_root[FS_MAX_PATH] = {0}; - errno = 0; - bool has_root = false; R_TRY(HasDirectory(&has_root, root_path)); if (!has_root) { @@ -118,13 +112,9 @@ namespace sts::ncm { if (path_len != 0) { for (size_t i = 0; i < path_len; i++) { if (i != 0 && working_path_buf[i + 1] == '/' && working_path_buf[i] != ':') { - /* Wipe the errno to prevent cross-contamination */ - errno = 0; /* Temporarily make the path terminate before the '/' */ working_path_buf[i + 1] = 0; - mkdir(working_path_buf + 1, S_IRWXU); - - if (errno != 0) { + if (mkdir(working_path_buf + 1, S_IRWXU) == -1) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathAlreadyExists) { /* If the path already exists, that's okay. Anything else is an error. */ diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index ce6a9c985..307631a76 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -142,10 +142,7 @@ namespace sts::ncm { } struct stat st; - errno = 0; - stat(content_path, &st); - - if (errno != 0) { + if (stat(content_path, &st) == -1) { return fsdevGetLastResult(); } @@ -186,23 +183,21 @@ namespace sts::ncm { path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); } - errno = 0; FILE* f = fopen(content_path, "rb"); - ON_SCOPE_EXIT { fclose(f); }; - if (f == NULL || errno != 0) { + if (f == nullptr) { return fsdevGetLastResult(); } + + if (!fseek(f, offset, SEEK_SET)) { + return fsdevGetLastResult(); + } - errno = 0; - fseek(f, offset, SEEK_SET); - fread(buf.buffer, buf.num_elements, 1, f); - - if (errno != 0) { - return fsdevGetLastResult(); + if (fread(buf.buffer, 1, buf.num_elements, f) != buf.num_elements && ferror(f)) { + return fsdevGetLastResult(); } return ResultSuccess; From 741d0f8116bbffb75abec9854c9d2fee2c72b7e8 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 13:32:49 +1000 Subject: [PATCH 12/58] Fixed more stdio error handling --- .../ncm/source/impl/ncm_placeholder_accessor.cpp | 4 ++-- stratosphere/ncm/source/ncm_contentstorage.cpp | 10 +++++----- stratosphere/ncm/source/ncm_readonlycontentstorage.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 5b6cf5d78..5bea9b33a 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -143,11 +143,11 @@ namespace sts::ncm::impl { this->StoreToCache(f, placeholder_id); - if (!fseek(f, 0L, SEEK_END)) { + if (fseek(f, 0L, SEEK_END) != 0) { return fsdevGetLastResult(); } size_t size = ftell(f); - if (!fseek(f, 0L, SEEK_SET)) { + if (fseek(f, 0L, SEEK_SET) != 0) { return fsdevGetLastResult(); } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 75255d69e..cd259df3f 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -158,7 +158,7 @@ namespace sts::ncm { } } R_END_TRY_CATCH; - if (!fseek(f, offset, SEEK_SET)) { + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -188,7 +188,7 @@ namespace sts::ncm { this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); this->GetContentPath(content_path, content_id); - if (!rename(placeholder_path, content_path)) { + if (rename(placeholder_path, content_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -423,7 +423,7 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - if (!rename(old_content_path, placeholder_path)) { + if (rename(old_content_path, placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -460,7 +460,7 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(this->OpenCachedContentFile(content_id)); - if (!fseek(this->content_cache_file_handle, offset, SEEK_SET)) { + if (fseek(this->content_cache_file_handle, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -582,7 +582,7 @@ namespace sts::ncm { return fsdevGetLastResult(); } - if (!fseek(f, offset, SEEK_SET)) { + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index 307631a76..246fa05b5 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -192,7 +192,7 @@ namespace sts::ncm { return fsdevGetLastResult(); } - if (!fseek(f, offset, SEEK_SET)) { + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } From 0169e3e3d61b8a5ae688d1b0ff115d04daeef527 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 19:56:54 +1000 Subject: [PATCH 13/58] More main fixes --- .../ncm/source/ncm_contentstorage.cpp | 2 +- stratosphere/ncm/source/ncm_main.cpp | 45 +++++++++++++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index cd259df3f..ab460e800 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -640,7 +640,7 @@ namespace sts::ncm { this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); if (stat(placeholder_path, &st) == -1) { - return fsdevGetLastResult();; + return fsdevGetLastResult(); } out_size.SetValue(st.st_size); diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 361153b9d..ef2140636 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -76,19 +76,48 @@ void __appExit(void) { fsExit(); } +struct ServerOptions { + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; +}; + +void ContentManagerServerMain(void* arg) { + static auto s_server_manager = WaitableManager(1); + + /* Create services. */ + s_server_manager.AddWaitable(new ServiceServer("ncm", 0x10)); + + /* Loop forever, servicing our services. */ + s_server_manager.Process(); +} + +void LocationResolverServerMain(void* arg) { + static auto s_server_manager = WaitableManager(1); + + /* Create services. */ + s_server_manager.AddWaitable(new ServiceServer("lr", 0x10)); + + /* Loop forever, servicing our services. */ + s_server_manager.Process(); +} + int main(int argc, char **argv) { - static auto s_server_manager = WaitableManager(2); - /* Initialize content manager implementation. */ R_ASSERT(sts::ncm::impl::InitializeContentManager()); - /* Create services. */ - s_server_manager.AddWaitable(new ServiceServer("ncm", 0x10)); - s_server_manager.AddWaitable(new ServiceServer("lr", 0x10)); - - /* Loop forever, servicing our services. */ - s_server_manager.Process(); + static HosThread s_content_manager_thread; + static HosThread s_location_resolver_thread; + + R_ASSERT(s_content_manager_thread.Initialize(&ContentManagerServerMain, nullptr, 0x4000, 0x15)); + R_ASSERT(s_content_manager_thread.Start()); + + R_ASSERT(s_location_resolver_thread.Initialize(&LocationResolverServerMain, nullptr, 0x4000, 0x15)); + R_ASSERT(s_location_resolver_thread.Start()); + + s_content_manager_thread.Join(); + s_location_resolver_thread.Join(); return 0; } \ No newline at end of file From e1023a59baa0ced0d99a5c9bbbf847ebfed79ca2 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 21:56:10 +1000 Subject: [PATCH 14/58] Various command improvements --- .../ncm/source/lr_contentlocationresolver.cpp | 14 +- .../ncm/source/lr_contentlocationresolver.hpp | 37 ++++- .../ncm/source/lr_ilocationresolver.cpp | 101 +++++++++++++ .../ncm/source/lr_ilocationresolver.hpp | 63 +++------ .../lr_redirectonlylocationresolver.cpp | 14 +- .../lr_redirectonlylocationresolver.hpp | 37 ++++- .../source/lr_registeredlocationresolver.cpp | 8 +- .../source/lr_registeredlocationresolver.hpp | 8 +- .../ncm/source/ncm_contentmetadatabase.hpp | 48 +++++++ .../ncm/source/ncm_contentstorage.hpp | 31 ++++ .../ncm/source/ncm_icontentmetadatabase.cpp | 113 +++++++++++++++ .../ncm/source/ncm_icontentmetadatabase.hpp | 70 +++------ .../ncm/source/ncm_icontentstorage.cpp | 133 ++++++++++++++++++ .../ncm/source/ncm_icontentstorage.hpp | 87 ++++-------- .../ncm/source/ncm_readonlycontentstorage.hpp | 31 ++++ 15 files changed, 610 insertions(+), 185 deletions(-) create mode 100644 stratosphere/ncm/source/lr_ilocationresolver.cpp create mode 100644 stratosphere/ncm/source/ncm_icontentmetadatabase.cpp create mode 100644 stratosphere/ncm/source/ncm_icontentstorage.cpp diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 54e4432ff..95680e8bd 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -48,7 +48,7 @@ namespace sts::lr { return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } @@ -85,12 +85,12 @@ namespace sts::lr { return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -106,7 +106,7 @@ namespace sts::lr { return ResultLrLegalInformationNotFound; } - Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -128,7 +128,7 @@ namespace sts::lr { return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -180,12 +180,12 @@ namespace sts::lr { return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } - Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) { + Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.hpp b/stratosphere/ncm/source/lr_contentlocationresolver.hpp index aa03d9ad4..ea3841053 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.hpp @@ -26,6 +26,29 @@ namespace sts::lr { class ContentLocationResolverInterface : public ILocationResolver { + private: + enum class CommandId { + ResolveProgramPath = 0, + RedirectProgramPath = 1, + ResolveApplicationControlPath = 2, + ResolveApplicationHtmlDocumentPath = 3, + ResolveDataPath = 4, + RedirectApplicationControlPath = 5, + RedirectApplicationHtmlDocumentPath = 6, + ResolveApplicationLegalInformationPath = 7, + RedirectApplicationLegalInformationPath = 8, + Refresh = 9, + RedirectApplicationProgramPath = 10, + ClearApplicationRedirection = 11, + EraseProgramRedirection = 12, + EraseApplicationControlRedirection = 13, + EraseApplicationHtmlDocumentRedirection = 14, + EraseApplicationLegalInformationRedirection = 15, + ResolveProgramPathForDebug = 16, + RedirectProgramPathForDebug = 17, + RedirectApplicationProgramPathForDebug = 18, + EraseProgramRedirectionForDebug = 19, + }; private: ncm::StorageId storage_id; std::shared_ptr content_meta_database; @@ -37,24 +60,24 @@ namespace sts::lr { ~ContentLocationResolverInterface(); public: virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectProgramPath(InPointer path, ncm::TitleId tid) override; virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) override; virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) override; virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) override; - virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) override; + virtual Result RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) override; virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) override; virtual Result Refresh() override; - virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) override; virtual Result ClearApplicationRedirection() override; virtual Result EraseProgramRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) override; virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) override; - virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) override; + virtual Result RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) override; virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) override; public: DEFINE_SERVICE_DISPATCH_TABLE { diff --git a/stratosphere/ncm/source/lr_ilocationresolver.cpp b/stratosphere/ncm/source/lr_ilocationresolver.cpp new file mode 100644 index 000000000..ef9bcf71f --- /dev/null +++ b/stratosphere/ncm/source/lr_ilocationresolver.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "lr_ilocationresolver.hpp" + +namespace sts::lr { + + Result ILocationResolver::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::Refresh() { + std::abort(); + } + + Result ILocationResolver::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ClearApplicationRedirection() { + std::abort(); + } + + Result ILocationResolver::EraseProgramRedirection(ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::EraseApplicationControlRedirection(ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + std::abort(); + } + + Result ILocationResolver::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + std::abort(); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_ilocationresolver.hpp b/stratosphere/ncm/source/lr_ilocationresolver.hpp index affc57397..b7d6149d6 100644 --- a/stratosphere/ncm/source/lr_ilocationresolver.hpp +++ b/stratosphere/ncm/source/lr_ilocationresolver.hpp @@ -23,29 +23,6 @@ namespace sts::lr { class ILocationResolver : public IServiceObject { - protected: - enum class CommandId { - ResolveProgramPath = 0, - RedirectProgramPath = 1, - ResolveApplicationControlPath = 2, - ResolveApplicationHtmlDocumentPath = 3, - ResolveDataPath = 4, - RedirectApplicationControlPath = 5, - RedirectApplicationHtmlDocumentPath = 6, - ResolveApplicationLegalInformationPath = 7, - RedirectApplicationLegalInformationPath = 8, - Refresh = 9, - RedirectApplicationProgramPath = 10, - ClearApplicationRedirection = 11, - EraseProgramRedirection = 12, - EraseApplicationControlRedirection = 13, - EraseApplicationHtmlDocumentRedirection = 14, - EraseApplicationLegalInformationRedirection = 15, - ResolveProgramPathForDebug = 16, - RedirectProgramPathForDebug = 17, - RedirectApplicationProgramPathForDebug = 18, - EraseProgramRedirectionForDebug = 19, - }; protected: impl::LocationRedirector program_redirector; impl::LocationRedirector debug_program_redirector; @@ -53,26 +30,26 @@ namespace sts::lr { impl::LocationRedirector html_docs_redirector; impl::LocationRedirector legal_info_redirector; public: - virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) = 0; - virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) = 0; - virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) = 0; - virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) = 0; - virtual Result Refresh() = 0; - virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) = 0; - virtual Result ClearApplicationRedirection() = 0; - virtual Result EraseProgramRedirection(ncm::TitleId tid) = 0; - virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) = 0; - virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) = 0; - virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) = 0; - virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) = 0; - virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) = 0; - virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) = 0; - virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) = 0; + virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result RedirectProgramPath(InPointer path, ncm::TitleId tid); + virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result RedirectApplicationControlPath(InPointer path, ncm::TitleId tid); + virtual Result RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid); + virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid); + virtual Result Refresh(); + virtual Result RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid); + virtual Result ClearApplicationRedirection(); + virtual Result EraseProgramRedirection(ncm::TitleId tid); + virtual Result EraseApplicationControlRedirection(ncm::TitleId tid); + virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid); + virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid); + virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid); + virtual Result RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid); + virtual Result RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid); + virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid); public: DEFINE_SERVICE_DISPATCH_TABLE {}; diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 0c4f3242f..b140e69b1 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -38,7 +38,7 @@ namespace sts::lr { return ResultLrProgramNotFound; } - Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } @@ -69,12 +69,12 @@ namespace sts::lr { return ResultLrDataNotFound; } - Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } - Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -90,7 +90,7 @@ namespace sts::lr { return ResultLrLegalInformationNotFound; } - Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -104,7 +104,7 @@ namespace sts::lr { return ResultSuccess; } - Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } @@ -156,12 +156,12 @@ namespace sts::lr { return ResultSuccess; } - Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } - Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) { + Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp index a963a1de6..dbfdaac57 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp @@ -23,28 +23,51 @@ namespace sts::lr { class RedirectOnlyLocationResolverInterface : public ILocationResolver { + private: + enum class CommandId { + ResolveProgramPath = 0, + RedirectProgramPath = 1, + ResolveApplicationControlPath = 2, + ResolveApplicationHtmlDocumentPath = 3, + ResolveDataPath = 4, + RedirectApplicationControlPath = 5, + RedirectApplicationHtmlDocumentPath = 6, + ResolveApplicationLegalInformationPath = 7, + RedirectApplicationLegalInformationPath = 8, + Refresh = 9, + RedirectApplicationProgramPath = 10, + ClearApplicationRedirection = 11, + EraseProgramRedirection = 12, + EraseApplicationControlRedirection = 13, + EraseApplicationHtmlDocumentRedirection = 14, + EraseApplicationLegalInformationRedirection = 15, + ResolveProgramPathForDebug = 16, + RedirectProgramPathForDebug = 17, + RedirectApplicationProgramPathForDebug = 18, + EraseProgramRedirectionForDebug = 19, + }; public: ~RedirectOnlyLocationResolverInterface(); public: virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectProgramPath(InPointer path, ncm::TitleId tid) override; virtual Result ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) override; virtual Result ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) override; virtual Result ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectApplicationControlPath(ncm::TitleId tid, InPointer path) override; - virtual Result RedirectApplicationHtmlDocumentPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) override; + virtual Result RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) override; virtual Result ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectApplicationLegalInformationPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) override; virtual Result Refresh() override; - virtual Result RedirectApplicationProgramPath(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) override; virtual Result ClearApplicationRedirection() override; virtual Result EraseProgramRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationControlRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) override; virtual Result EraseApplicationLegalInformationRedirection(ncm::TitleId tid) override; virtual Result ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) override; - virtual Result RedirectProgramPathForDebug(ncm::TitleId tid, InPointer path) override; - virtual Result RedirectApplicationProgramPathForDebug(ncm::TitleId tid, InPointer path) override; + virtual Result RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) override; + virtual Result RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) override; virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid) override; public: DEFINE_SERVICE_DISPATCH_TABLE { diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 384945199..a21c41120 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -42,7 +42,7 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RegisterProgramPath(ncm::TitleId tid, InPointer path) { + Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -58,7 +58,7 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RedirectProgramPath(ncm::TitleId tid, InPointer path) { + Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; @@ -77,7 +77,7 @@ namespace sts::lr { return ResultLrHtmlDocumentNotFound; } - Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -93,7 +93,7 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(ncm::TitleId tid, InPointer path) { + Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index 8ab09863a..3c40f9462 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -46,13 +46,13 @@ namespace sts::lr { ~RegisteredLocationResolverInterface(); Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); - Result RegisterProgramPath(ncm::TitleId tid, InPointer path); + Result RegisterProgramPath(InPointer path, ncm::TitleId tid); Result UnregisterProgramPath(ncm::TitleId tid); - Result RedirectProgramPath(ncm::TitleId tid, InPointer path); + Result RedirectProgramPath(InPointer path, ncm::TitleId tid); Result ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid); - Result RegisterHtmlDocumentPath(ncm::TitleId tid, InPointer path); + Result RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid); Result UnregisterHtmlDocumentPath(ncm::TitleId tid); - Result RedirectHtmlDocumentPath(ncm::TitleId tid, InPointer path); + Result RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid); Result Refresh(); public: DEFINE_SERVICE_DISPATCH_TABLE { diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp index faca1e8f3..64c3a8492 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -23,6 +23,30 @@ namespace sts::ncm { class ContentMetaDatabaseInterface : public IContentMetaDatabase { + private: + 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: ContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs, const char* mount_name) : IContentMetaDatabase(kvs, mount_name) { } @@ -84,6 +108,30 @@ namespace sts::ncm { }; class OnMemoryContentMetaDatabaseInterface : public ContentMetaDatabaseInterface { + private: + 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: OnMemoryContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs) : ContentMetaDatabaseInterface(kvs) { } diff --git a/stratosphere/ncm/source/ncm_contentstorage.hpp b/stratosphere/ncm/source/ncm_contentstorage.hpp index df124f9bd..d69b115f7 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.hpp +++ b/stratosphere/ncm/source/ncm_contentstorage.hpp @@ -25,6 +25,37 @@ namespace sts::ncm { class ContentStorageInterface : public IContentStorage { + private: + 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, + GetRightsIdFromPlaceHolderId = 19, + GetRightsIdFromContentId = 20, + WriteContentForDebug = 21, + GetFreeSpaceSize = 22, + GetTotalSpaceSize = 23, + FlushPlaceHolder = 24, + GetSizeFromPlaceHolderId = 25, + RepairInvalidFileAttribute = 26, + GetRightsIdFromPlaceHolderIdWithCache = 27, + }; protected: impl::PlaceHolderAccessor placeholder_accessor; ContentId cached_content_id; diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp new file mode 100644 index 000000000..7512ccc15 --- /dev/null +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_icontentmetadatabase.hpp" + +namespace sts::ncm { + + Result IContentMetaDatabase::Set(ContentMetaKey key, InBuffer value) { + std::abort(); + } + + Result IContentMetaDatabase::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { + std::abort(); + } + + Result IContentMetaDatabase::Remove(ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { + std::abort(); + } + + Result IContentMetaDatabase::ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) { + std::abort(); + } + + Result IContentMetaDatabase::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { + std::abort(); + } + + Result IContentMetaDatabase::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + std::abort(); + } + + Result IContentMetaDatabase::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { + std::abort(); + } + + Result IContentMetaDatabase::Has(Out out, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::HasAll(Out out, InBuffer keys) { + std::abort(); + } + + Result IContentMetaDatabase::GetSize(Out out_size, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::GetPatchId(Out out_patch_id, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::DisableForcibly() { + std::abort(); + } + + Result IContentMetaDatabase::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + std::abort(); + } + + Result IContentMetaDatabase::Commit() { + std::abort(); + } + + Result IContentMetaDatabase::HasContent(Out out, ContentMetaKey key, ContentId content_id) { + std::abort(); + } + + Result IContentMetaDatabase::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { + std::abort(); + } + + Result IContentMetaDatabase::GetAttributes(Out out_attributes, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { + std::abort(); + } + + Result IContentMetaDatabase::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { + std::abort(); + } + + Result IContentMetaDatabase::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { + std::abort(); + } + + Result IContentMetaDatabase::GetLatestData(ContentId* out_content_id, TitleId title_id) { + std::abort(); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp index c094f38f2..2fec2aa92 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -24,30 +24,6 @@ namespace sts::ncm { class IContentMetaDatabase : public 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, - }; protected: sts::kvdb::MemoryKeyValueStore* kvs; char mount_name[16]; @@ -65,31 +41,31 @@ namespace sts::ncm { } public: /* Actual commands. */ - virtual Result Set(ContentMetaKey key, InBuffer value) = 0; - virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value) = 0; - virtual Result Remove(ContentMetaKey key) = 0; - virtual Result GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) = 0; - virtual Result ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) = 0; - virtual Result List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType meta_type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) = 0; - virtual Result GetLatestContentMetaKey(Out out_key, TitleId tid) = 0; - virtual Result ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType meta_type) = 0; - virtual Result Has(Out out, ContentMetaKey key) = 0; - virtual Result HasAll(Out out, InBuffer keys) = 0; - virtual Result GetSize(Out out_size, ContentMetaKey key) = 0; - virtual Result GetRequiredSystemVersion(Out out_version, ContentMetaKey key) = 0; - virtual Result GetPatchId(Out out_patch_id, ContentMetaKey key) = 0; - virtual Result DisableForcibly() = 0; - virtual Result LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) = 0; - virtual Result Commit() = 0; - virtual Result HasContent(Out out, ContentMetaKey key, ContentId content_id) = 0; - virtual Result ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) = 0; - virtual Result GetAttributes(Out out_attributes, ContentMetaKey key) = 0; - virtual Result GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) = 0; - virtual Result GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) = 0; + virtual Result Set(ContentMetaKey key, InBuffer value); + virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value); + virtual Result Remove(ContentMetaKey key); + virtual Result GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type); + virtual Result ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index); + virtual Result List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType meta_type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type); + virtual Result GetLatestContentMetaKey(Out out_key, TitleId tid); + virtual Result ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType meta_type); + virtual Result Has(Out out, ContentMetaKey key); + virtual Result HasAll(Out out, InBuffer keys); + virtual Result GetSize(Out out_size, ContentMetaKey key); + virtual Result GetRequiredSystemVersion(Out out_version, ContentMetaKey key); + virtual Result GetPatchId(Out out_patch_id, ContentMetaKey key); + virtual Result DisableForcibly(); + virtual Result LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids); + virtual Result Commit(); + virtual Result HasContent(Out out, ContentMetaKey key, ContentId content_id); + virtual Result ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index); + virtual Result GetAttributes(Out out_attributes, ContentMetaKey key); + virtual Result GetRequiredApplicationVersion(Out out_version, ContentMetaKey key); + virtual Result GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset); /* APIs. */ - virtual Result GetLatestProgram(ContentId* out_content_id, TitleId title_id) = 0; - virtual Result GetLatestData(ContentId* out_content_id, TitleId title_id) = 0; + virtual Result GetLatestProgram(ContentId* out_content_id, TitleId title_id); + virtual Result GetLatestData(ContentId* out_content_id, TitleId title_id); public: DEFINE_SERVICE_DISPATCH_TABLE {}; }; diff --git a/stratosphere/ncm/source/ncm_icontentstorage.cpp b/stratosphere/ncm/source/ncm_icontentstorage.cpp new file mode 100644 index 000000000..26db32fc5 --- /dev/null +++ b/stratosphere/ncm/source/ncm_icontentstorage.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#include "ncm_icontentstorage.hpp" + +namespace sts::ncm { + + Result IContentStorage::GeneratePlaceHolderId(Out out) { + std::abort(); + } + + Result IContentStorage::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + std::abort(); + } + + Result IContentStorage::DeletePlaceHolder(PlaceHolderId placeholder_id) { + std::abort(); + } + + Result IContentStorage::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + std::abort(); + } + + Result IContentStorage::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + std::abort(); + } + + Result IContentStorage::Register(PlaceHolderId placeholder_id, ContentId content_id) { + std::abort(); + } + + Result IContentStorage::Delete(ContentId content_id) { + std::abort(); + } + + Result IContentStorage::Has(Out out, ContentId content_id) { + std::abort(); + } + + Result IContentStorage::GetPath(OutPointerWithServerSize out, ContentId content_id) { + std::abort(); + } + + Result IContentStorage::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + std::abort(); + } + + Result IContentStorage::CleanupAllPlaceHolder() { + std::abort(); + } + + Result IContentStorage::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + std::abort(); + } + + Result IContentStorage::GetContentCount(Out out_count) { + std::abort(); + } + + Result IContentStorage::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + std::abort(); + } + + Result IContentStorage::GetSizeFromContentId(Out out_size, ContentId content_id) { + std::abort(); + } + + Result IContentStorage::DisableForcibly() { + std::abort(); + } + + Result IContentStorage::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + std::abort(); + } + + Result IContentStorage::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + std::abort(); + } + + Result IContentStorage::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + std::abort(); + } + + Result IContentStorage::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + std::abort(); + } + + Result IContentStorage::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + std::abort(); + } + + Result IContentStorage::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + std::abort(); + } + + Result IContentStorage::GetFreeSpaceSize(Out out_size) { + std::abort(); + } + + Result IContentStorage::GetTotalSpaceSize(Out out_size) { + std::abort(); + } + + Result IContentStorage::FlushPlaceHolder() { + std::abort(); + } + + Result IContentStorage::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { + std::abort(); + } + + Result IContentStorage::RepairInvalidFileAttribute() { + std::abort(); + } + + Result IContentStorage::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + std::abort(); + } + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index a583c937c..7ac4b6c78 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -24,70 +24,39 @@ namespace sts::ncm { class IContentStorage : public IServiceObject { - 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, - GetRightsIdFromPlaceHolderId = 19, - GetRightsIdFromContentId = 20, - WriteContentForDebug = 21, - GetFreeSpaceSize = 22, - GetTotalSpaceSize = 23, - FlushPlaceHolder = 24, - GetSizeFromPlaceHolderId = 25, - RepairInvalidFileAttribute = 26, - GetRightsIdFromPlaceHolderIdWithCache = 27, - }; protected: char root_path[FS_MAX_PATH-1]; MakeContentPathFunc make_content_path_func; bool disabled; public: - virtual Result GeneratePlaceHolderId(Out out) = 0; - virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) = 0; - virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id) = 0; - virtual Result HasPlaceHolder(Out out, PlaceHolderId placeholder_id) = 0; - virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) = 0; - virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id) = 0; - virtual Result Delete(ContentId content_id) = 0; - virtual Result Has(Out out, ContentId content_id) = 0; - virtual Result GetPath(OutPointerWithServerSize out, ContentId content_id) = 0; - virtual Result GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) = 0; - virtual Result CleanupAllPlaceHolder() = 0; - virtual Result ListPlaceHolder(Out out_count, OutBuffer out_buf) = 0; - virtual Result GetContentCount(Out out_count) = 0; - virtual Result ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) = 0; - virtual Result GetSizeFromContentId(Out 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, u64 size) = 0; - virtual Result ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) = 0; - virtual Result GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) = 0; - virtual Result GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) = 0; - virtual Result WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) = 0; - virtual Result GetFreeSpaceSize(Out out_size) = 0; - virtual Result GetTotalSpaceSize(Out out_size) = 0; - virtual Result FlushPlaceHolder() = 0; - virtual Result GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) = 0; - virtual Result RepairInvalidFileAttribute() = 0; - virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) = 0; + virtual Result GeneratePlaceHolderId(Out out); + virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size); + virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id); + virtual Result HasPlaceHolder(Out out, PlaceHolderId placeholder_id); + virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data); + virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id); + virtual Result Delete(ContentId content_id); + virtual Result Has(Out out, ContentId content_id); + virtual Result GetPath(OutPointerWithServerSize out, ContentId content_id); + virtual Result GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id); + virtual Result CleanupAllPlaceHolder(); + virtual Result ListPlaceHolder(Out out_count, OutBuffer out_buf); + virtual Result GetContentCount(Out out_count); + virtual Result ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset); + virtual Result GetSizeFromContentId(Out out_size, ContentId content_id); + virtual Result DisableForcibly(); + virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id); + virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size); + virtual Result ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset); + virtual Result GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id); + virtual Result GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id); + virtual Result WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data); + virtual Result GetFreeSpaceSize(Out out_size); + virtual Result GetTotalSpaceSize(Out out_size); + virtual Result FlushPlaceHolder(); + virtual Result GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id); + virtual Result RepairInvalidFileAttribute(); + virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id); public: DEFINE_SERVICE_DISPATCH_TABLE {}; }; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp index 135690230..169d814b8 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp @@ -23,6 +23,37 @@ namespace sts::ncm { class ReadOnlyContentStorageInterface : public IContentStorage { + private: + 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, + GetRightsIdFromPlaceHolderId = 19, + GetRightsIdFromContentId = 20, + WriteContentForDebug = 21, + GetFreeSpaceSize = 22, + GetTotalSpaceSize = 23, + FlushPlaceHolder = 24, + GetSizeFromPlaceHolderId = 25, + RepairInvalidFileAttribute = 26, + GetRightsIdFromPlaceHolderIdWithCache = 27, + }; public: Result Initialize(const char* root_path, MakeContentPathFunc content_path_func); public: From 6b35b0d6ad5a653c6bd96a7f3a75c80e6c8a5e67 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 22:19:04 +1000 Subject: [PATCH 15/58] Make dispatch tables great again --- .../ncm/source/lr_contentlocationresolver.hpp | 23 ------- .../ncm/source/lr_ilocationresolver.hpp | 47 +++++++++++++- .../lr_redirectonlylocationresolver.hpp | 23 ------- .../ncm/source/ncm_contentmetadatabase.hpp | 24 ------- .../ncm/source/ncm_contentstorage.hpp | 31 --------- .../ncm/source/ncm_icontentmetadatabase.hpp | 48 +++++++++++++- .../ncm/source/ncm_icontentstorage.hpp | 63 ++++++++++++++++++- .../ncm/source/ncm_readonlycontentstorage.hpp | 31 --------- 8 files changed, 154 insertions(+), 136 deletions(-) diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.hpp b/stratosphere/ncm/source/lr_contentlocationresolver.hpp index ea3841053..e5a59370c 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.hpp @@ -26,29 +26,6 @@ namespace sts::lr { class ContentLocationResolverInterface : public ILocationResolver { - private: - enum class CommandId { - ResolveProgramPath = 0, - RedirectProgramPath = 1, - ResolveApplicationControlPath = 2, - ResolveApplicationHtmlDocumentPath = 3, - ResolveDataPath = 4, - RedirectApplicationControlPath = 5, - RedirectApplicationHtmlDocumentPath = 6, - ResolveApplicationLegalInformationPath = 7, - RedirectApplicationLegalInformationPath = 8, - Refresh = 9, - RedirectApplicationProgramPath = 10, - ClearApplicationRedirection = 11, - EraseProgramRedirection = 12, - EraseApplicationControlRedirection = 13, - EraseApplicationHtmlDocumentRedirection = 14, - EraseApplicationLegalInformationRedirection = 15, - ResolveProgramPathForDebug = 16, - RedirectProgramPathForDebug = 17, - RedirectApplicationProgramPathForDebug = 18, - EraseProgramRedirectionForDebug = 19, - }; private: ncm::StorageId storage_id; std::shared_ptr content_meta_database; diff --git a/stratosphere/ncm/source/lr_ilocationresolver.hpp b/stratosphere/ncm/source/lr_ilocationresolver.hpp index b7d6149d6..2b4a7bef8 100644 --- a/stratosphere/ncm/source/lr_ilocationresolver.hpp +++ b/stratosphere/ncm/source/lr_ilocationresolver.hpp @@ -23,6 +23,29 @@ namespace sts::lr { class ILocationResolver : public IServiceObject { + protected: + enum class CommandId { + ResolveProgramPath = 0, + RedirectProgramPath = 1, + ResolveApplicationControlPath = 2, + ResolveApplicationHtmlDocumentPath = 3, + ResolveDataPath = 4, + RedirectApplicationControlPath = 5, + RedirectApplicationHtmlDocumentPath = 6, + ResolveApplicationLegalInformationPath = 7, + RedirectApplicationLegalInformationPath = 8, + Refresh = 9, + RedirectApplicationProgramPath = 10, + ClearApplicationRedirection = 11, + EraseProgramRedirection = 12, + EraseApplicationControlRedirection = 13, + EraseApplicationHtmlDocumentRedirection = 14, + EraseApplicationLegalInformationRedirection = 15, + ResolveProgramPathForDebug = 16, + RedirectProgramPathForDebug = 17, + RedirectApplicationProgramPathForDebug = 18, + EraseProgramRedirectionForDebug = 19, + }; protected: impl::LocationRedirector program_redirector; impl::LocationRedirector debug_program_redirector; @@ -50,9 +73,29 @@ namespace sts::lr { virtual Result RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid); virtual Result RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid); virtual Result EraseProgramRedirectionForDebug(ncm::TitleId tid); - public: - DEFINE_SERVICE_DISPATCH_TABLE {}; + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveProgramPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectProgramPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveApplicationControlPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveDataPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectApplicationControlPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectApplicationHtmlDocumentPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectApplicationLegalInformationPath), + MAKE_SERVICE_COMMAND_META(ILocationResolver, Refresh), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectApplicationProgramPath, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ClearApplicationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, EraseProgramRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, EraseApplicationControlRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, EraseApplicationHtmlDocumentRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, EraseApplicationLegalInformationRedirection, FirmwareVersion_500), + MAKE_SERVICE_COMMAND_META(ILocationResolver, ResolveProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ILocationResolver, RedirectApplicationProgramPathForDebug, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ILocationResolver, EraseProgramRedirectionForDebug, FirmwareVersion_700), + }; }; } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp index dbfdaac57..e69696d18 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp @@ -23,29 +23,6 @@ namespace sts::lr { class RedirectOnlyLocationResolverInterface : public ILocationResolver { - private: - enum class CommandId { - ResolveProgramPath = 0, - RedirectProgramPath = 1, - ResolveApplicationControlPath = 2, - ResolveApplicationHtmlDocumentPath = 3, - ResolveDataPath = 4, - RedirectApplicationControlPath = 5, - RedirectApplicationHtmlDocumentPath = 6, - ResolveApplicationLegalInformationPath = 7, - RedirectApplicationLegalInformationPath = 8, - Refresh = 9, - RedirectApplicationProgramPath = 10, - ClearApplicationRedirection = 11, - EraseProgramRedirection = 12, - EraseApplicationControlRedirection = 13, - EraseApplicationHtmlDocumentRedirection = 14, - EraseApplicationLegalInformationRedirection = 15, - ResolveProgramPathForDebug = 16, - RedirectProgramPathForDebug = 17, - RedirectApplicationProgramPathForDebug = 18, - EraseProgramRedirectionForDebug = 19, - }; public: ~RedirectOnlyLocationResolverInterface(); public: diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp index 64c3a8492..b306631e3 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -23,30 +23,6 @@ namespace sts::ncm { class ContentMetaDatabaseInterface : public IContentMetaDatabase { - private: - 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: ContentMetaDatabaseInterface(sts::kvdb::MemoryKeyValueStore* kvs, const char* mount_name) : IContentMetaDatabase(kvs, mount_name) { } diff --git a/stratosphere/ncm/source/ncm_contentstorage.hpp b/stratosphere/ncm/source/ncm_contentstorage.hpp index d69b115f7..df124f9bd 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.hpp +++ b/stratosphere/ncm/source/ncm_contentstorage.hpp @@ -25,37 +25,6 @@ namespace sts::ncm { class ContentStorageInterface : public IContentStorage { - private: - 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, - GetRightsIdFromPlaceHolderId = 19, - GetRightsIdFromContentId = 20, - WriteContentForDebug = 21, - GetFreeSpaceSize = 22, - GetTotalSpaceSize = 23, - FlushPlaceHolder = 24, - GetSizeFromPlaceHolderId = 25, - RepairInvalidFileAttribute = 26, - GetRightsIdFromPlaceHolderIdWithCache = 27, - }; protected: impl::PlaceHolderAccessor placeholder_accessor; ContentId cached_content_id; diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp index 2fec2aa92..4a9855f91 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -24,6 +24,30 @@ namespace sts::ncm { class IContentMetaDatabase : public 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, + }; protected: sts::kvdb::MemoryKeyValueStore* kvs; char mount_name[16]; @@ -67,7 +91,29 @@ namespace sts::ncm { virtual Result GetLatestProgram(ContentId* out_content_id, TitleId title_id); virtual Result GetLatestData(ContentId* out_content_id, TitleId title_id); public: - DEFINE_SERVICE_DISPATCH_TABLE {}; + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, Set), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, Get), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, Remove), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetContentIdByType), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, ListContentInfo), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, List), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetLatestContentMetaKey), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, ListApplication), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, Has), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, HasAll), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetSize), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetRequiredSystemVersion), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetPatchId), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, DisableForcibly), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, LookupOrphanContent), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, Commit), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, HasContent), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, ListContentMetaInfo), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetAttributes), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetRequiredApplicationVersion, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentMetaDatabase, GetContentIdByTypeAndIdOffset, FirmwareVersion_500), + }; }; } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index 7ac4b6c78..6e58ea6c6 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -24,6 +24,37 @@ namespace sts::ncm { class IContentStorage : public IServiceObject { + 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, + GetRightsIdFromPlaceHolderId = 19, + GetRightsIdFromContentId = 20, + WriteContentForDebug = 21, + GetFreeSpaceSize = 22, + GetTotalSpaceSize = 23, + FlushPlaceHolder = 24, + GetSizeFromPlaceHolderId = 25, + RepairInvalidFileAttribute = 26, + GetRightsIdFromPlaceHolderIdWithCache = 27, + }; protected: char root_path[FS_MAX_PATH-1]; MakeContentPathFunc make_content_path_func; @@ -58,7 +89,37 @@ namespace sts::ncm { virtual Result RepairInvalidFileAttribute(); virtual Result GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id); public: - DEFINE_SERVICE_DISPATCH_TABLE {}; + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(IContentStorage, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(IContentStorage, CreatePlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, DeletePlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, HasPlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, WritePlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, Register), + MAKE_SERVICE_COMMAND_META(IContentStorage, Delete), + MAKE_SERVICE_COMMAND_META(IContentStorage, Has), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetPath), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetPlaceHolderPath), + MAKE_SERVICE_COMMAND_META(IContentStorage, CleanupAllPlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, ListPlaceHolder), + MAKE_SERVICE_COMMAND_META(IContentStorage, GeneratePlaceHolderId), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetContentCount), + MAKE_SERVICE_COMMAND_META(IContentStorage, ListContentId), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetSizeFromContentId), + MAKE_SERVICE_COMMAND_META(IContentStorage, DisableForcibly), + MAKE_SERVICE_COMMAND_META(IContentStorage, RevertToPlaceHolder, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, SetPlaceHolderSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, ReadContentIdFile, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetRightsIdFromPlaceHolderId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetRightsIdFromContentId, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, WriteContentForDebug, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetFreeSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetTotalSpaceSize, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(IContentStorage, FlushPlaceHolder, FirmwareVersion_300), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetSizeFromPlaceHolderId, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(IContentStorage, RepairInvalidFileAttribute, FirmwareVersion_400), + MAKE_SERVICE_COMMAND_META(IContentStorage, GetRightsIdFromPlaceHolderIdWithCache, FirmwareVersion_800), + }; }; } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp index 169d814b8..135690230 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp @@ -23,37 +23,6 @@ namespace sts::ncm { class ReadOnlyContentStorageInterface : public IContentStorage { - private: - 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, - GetRightsIdFromPlaceHolderId = 19, - GetRightsIdFromContentId = 20, - WriteContentForDebug = 21, - GetFreeSpaceSize = 22, - GetTotalSpaceSize = 23, - FlushPlaceHolder = 24, - GetSizeFromPlaceHolderId = 25, - RepairInvalidFileAttribute = 26, - GetRightsIdFromPlaceHolderIdWithCache = 27, - }; public: Result Initialize(const char* root_path, MakeContentPathFunc content_path_func); public: From ebc619fe56ad41002ee7882781a4f659d034239b Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 23:11:17 +1000 Subject: [PATCH 16/58] Fix logic inversion --- stratosphere/ncm/source/ncm_contentmetadatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index b544de8e6..5c4de4830 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -169,7 +169,7 @@ namespace sts::ncm { break; } - if (entry->GetKey().install_type != ContentInstallType::Full) { + if (entry->GetKey().install_type == ContentInstallType::Full) { key = entry->GetKey(); found_key = true; } From 7a81ca94415b1c318c79254651d2451ac6393733 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 27 Jul 2019 23:43:54 +1000 Subject: [PATCH 17/58] Fixed content path generation --- stratosphere/ncm/source/ncm_fs.cpp | 2 +- stratosphere/ncm/source/ncm_utils.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 1d1a38e20..3fecec315 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -272,7 +272,7 @@ namespace sts::ncm { std::abort(); } - snprintf(out_common_path, out_len, "%s:/%s", common_mount_name, translated_path); + snprintf(out_common_path, out_len, "%s:%s", common_mount_name, translated_path); return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_utils.cpp b/stratosphere/ncm/source/ncm_utils.cpp index 8be26bf71..a490f6a0f 100644 --- a/stratosphere/ncm/source/ncm_utils.cpp +++ b/stratosphere/ncm/source/ncm_utils.cpp @@ -20,13 +20,13 @@ namespace sts::ncm { void GetStringFromContentId(char* out, ContentId content_id) { for (size_t i = 0; i < sizeof(ContentId); i++) { - snprintf(out+i, 3, "%02x", content_id.uuid[i]); + snprintf(out+i*2, 3, "%02x", content_id.uuid[i]); } } void GetStringFromPlaceHolderId(char* out, PlaceHolderId placeholder_id) { for (size_t i = 0; i < sizeof(PlaceHolderId); i++) { - snprintf(out+i, 3, "%02x", placeholder_id.uuid[i]); + snprintf(out+i*2, 3, "%02x", placeholder_id.uuid[i]); } } From b2dd198dc8ff528d30eebfec6e3db496bdb6fce9 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 3 Aug 2019 22:50:56 +1000 Subject: [PATCH 18/58] Bump heap size, fix CleanupAllPlaceHolder --- stratosphere/ncm/source/ncm_contentstorage.cpp | 6 ++++++ stratosphere/ncm/source/ncm_main.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index ab460e800..4369e0877 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -272,8 +272,14 @@ namespace sts::ncm { this->placeholder_accessor.ClearAllCaches(); this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + /* Nintendo uses CleanDirectoryRecursively which is 3.0.0+. + We'll just delete the directory and recreate it to support all firmwares. */ R_TRY(fsdevDeleteDirectoryRecursively(placeholder_root_path)); + if (mkdir(placeholder_root_path, S_IRWXU) == -1) { + return fsdevGetLastResult(); + } + return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index ef2140636..2c450e540 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -28,6 +28,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; #define INNER_HEAP_SIZE 0x60000 + #define INNER_HEAP_SIZE 0x100000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; From ef28b7d3955636447a3aaf34859e05b1cebc5f28 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sun, 4 Aug 2019 13:10:45 +1000 Subject: [PATCH 19/58] Various fixes. Note: This contains debug stuff which will be removed later. I was getting tired of having to cherrypick tiny changes --- stratosphere/ncm/source/debug.cpp | 142 +++++++++++ stratosphere/ncm/source/debug.hpp | 39 +++ .../ncm/source/impl/ncm_content_manager.cpp | 6 +- .../source/impl/ncm_placeholder_accessor.cpp | 5 + .../ncm/source/lr_contentlocationresolver.cpp | 42 ++++ .../ncm/source/lr_manager_service.cpp | 11 + .../lr_redirectonlylocationresolver.cpp | 28 +++ .../source/lr_registeredlocationresolver.cpp | 20 ++ .../source/ncm_content_manager_service.cpp | 28 +++ .../ncm/source/ncm_contentmetadatabase.cpp | 231 ++++++++---------- .../ncm/source/ncm_contentmetadatabase.hpp | 2 + .../ncm/source/ncm_contentstorage.cpp | 58 +++++ stratosphere/ncm/source/ncm_fs.cpp | 60 +++-- stratosphere/ncm/source/ncm_main.cpp | 43 +++- .../ncm/source/ncm_readonlycontentstorage.cpp | 60 +++++ stratosphere/ncm/source/ncm_types.hpp | 38 ++- 16 files changed, 639 insertions(+), 174 deletions(-) create mode 100644 stratosphere/ncm/source/debug.cpp create mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp new file mode 100644 index 000000000..6659ae10f --- /dev/null +++ b/stratosphere/ncm/source/debug.cpp @@ -0,0 +1,142 @@ +#include + +#include "impl/ncm_content_manager.hpp" +#include "debug.hpp" +#include "ncm_fs.hpp" + +namespace sts::debug { + + #define IRAM_BASE 0x40000000ull + #define IRAM_SIZE 0x40000 + + #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 + #define IRAM_PAYLOAD_BASE 0x40010000ull + + #define IRAM_SAFE_START 0x40038000ull + #define IRAM_SAFE_END 0x4003D000ull + #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START + + namespace { + + HosMutex g_log_mutex; + + } + + size_t g_curr_log_offset = 0; + size_t g_log_skip = 4; + + char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; + + void clear_iram(void) { + /* Fill with null*/ + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Overwrite all of our log's IRAM with 0s. */ + for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); + } + } + + void clear_log(void) { + std::scoped_lock lk(g_log_mutex); + + clear_iram(); + } + + Result Initialize() { + clear_log(); + return ResultSuccess; + } + + void DebugLog(const char* format, ...) { + std::scoped_lock lk(g_log_mutex); + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Format a string with our arguments. */ + va_list args; + va_start(args, format); + vsnprintf(g_work_page, 0x1000, format, args); + va_end(args); + + size_t msg_len = strnlen(g_work_page, 0x1000); + + /* Nothing to log. */ + if (msg_len == 0) { + return; + } + + /* Attempt to put some of our new string in the previous 4 bytes. */ + if (g_curr_log_offset >= 4) { + char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; + CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); + size_t prev_4_size = strnlen(prev_4, 4); + + /* Do we have room to put some of our new string in the old one? */ + if (prev_4_size < 4) { + size_t spare_4_space = 4 - prev_4_size; + memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); + + /* Copy the previous 4 bytes back. */ + CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); + memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); + /* Update our size again. */ + msg_len = strnlen(g_work_page, 0x1000); + } + } + + size_t msg_len_aligned = (msg_len + 3) & ~3; + + if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { + if (g_log_skip == 0) { + /* Log is full. Reboot to RCM to read it. */ + RebootToRcm(); + return; + } + + g_log_skip--; + clear_iram(); + g_curr_log_offset = 0; + } + + /* Fill remainder with 0s. */ + if (msg_len_aligned > msg_len) { + memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); + } + + uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; + uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); + + /* We are copying across two pages */ + if (iram_out_start + msg_len_aligned > iram_next_page) { + size_t first_page_size = iram_next_page - iram_out_start; + CopyToIram(iram_out_start, g_work_page, first_page_size); + CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); + } else { + CopyToIram(iram_out_start, g_work_page, msg_len_aligned); + } + + g_curr_log_offset += msg_len_aligned; + } + + void LogBytes(const void* buf, size_t len) { + if (buf == NULL || len == 0) { + return; + } + + const u8* bytes = static_cast(buf); + int count = 0; + DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); + DebugLog("-----------------------------------------------\n"); + + for (size_t i = 0; i < len; i++) { + DebugLog("%02x ", bytes[i]); + count++; + if ((count % 16) == 0) { + DebugLog("\n"); + } + } + + DebugLog("\n"); + } +} + diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp new file mode 100644 index 000000000..0eca28d9a --- /dev/null +++ b/stratosphere/ncm/source/debug.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +namespace sts::debug { + #define STR_(X) #X + #define STR(X) STR_(X) + + #define D_LOG(format, ...) \ + debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); + #define R_DEBUG_START \ + Result rc = [&]() -> Result { + #define R_DEBUG_END \ + }(); \ + D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ + return rc; + + Result Initialize(); + void DebugLog(const char* format, ...); + void LogBytes(const void* buf, size_t len); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 9477e1841..dcfe4326f 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,6 +19,7 @@ #include #include +#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -62,7 +63,7 @@ namespace sts::ncm::impl { u64 journal_size; u32 flags; FsSaveDataSpaceId space_id; - } PACKED; + }; static_assert(sizeof(SaveDataMeta) == 0x20, "SaveDataMeta definition!"); @@ -150,6 +151,9 @@ namespace sts::ncm::impl { return ResultSuccess; } + R_ASSERT(debug::Initialize()); + debug::DebugLog("ContentManager::InitializeContentManager\n"); + size_t cur_storage_index = g_num_content_storage_entries; for (size_t i = 0; i < MaxContentStorageEntries; i++) { diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 5bea9b33a..c3236a4c8 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,6 +20,8 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" +#include "../debug.hpp" + namespace sts::ncm::impl { unsigned int PlaceHolderAccessor::GetDirectoryDepth() { @@ -78,6 +80,8 @@ namespace sts::ncm::impl { this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + debug::DebugLog("Deleting %s\n", placeholder_path); + R_TRY_CATCH(fsdevDeleteDirectoryRecursively(placeholder_path)) { R_CATCH(ResultFsPathNotFound) { return ResultNcmPlaceHolderNotFound; @@ -97,6 +101,7 @@ namespace sts::ncm::impl { FILE* f = fopen(placeholder_path, "r+b"); if (f == nullptr) { + debug::DebugLog("Failed to open placeholder %s\n", placeholder_path); return fsdevGetLastResult(); } diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 95680e8bd..ddbffc45e 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -46,14 +49,18 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -62,9 +69,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -73,9 +82,11 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::ContentId data_content_id; @@ -83,19 +94,25 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -104,14 +121,18 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { + R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -126,43 +147,57 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -178,21 +213,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index b6311dc93..82b11f7ec 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -13,26 +13,37 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" +#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { + R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); + R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { + R_DEBUG_START + D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index b140e69b1..8f626f3ce 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -36,14 +39,18 @@ namespace sts::lr { } return ResultLrProgramNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -52,9 +59,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -63,23 +72,31 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START return ResultLrDataNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -88,39 +105,50 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { + R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index a21c41120..1b5197fe8 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,6 +16,8 @@ #include "lr_registeredlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -30,6 +32,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -40,9 +43,11 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -51,20 +56,26 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -75,9 +86,11 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -86,23 +99,30 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { + R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index 2418dbd09..80f82ae13 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + namespace sts::ncm { ContentManagerService::~ContentManagerService() { @@ -24,61 +26,87 @@ namespace sts::ncm { } Result ContentManagerService::CreateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { + R_DEBUG_START std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { + R_DEBUG_START std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 5c4de4830..47c8d3ce3 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,6 +17,8 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { namespace { @@ -91,9 +93,7 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_TRY(this->EnsureEnabled()); const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { @@ -146,25 +146,13 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::GetLatestContentMetaKeyImpl(ContentMetaKey* out_key, TitleId tid) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_TRY(this->EnsureEnabled()); ContentMetaKey key = {0}; key.id = tid; - if (this->kvs->GetCount() == 0) { - return ResultNcmContentMetaNotFound; - } - - auto entry = this->kvs->lower_bound(key); - if (entry == this->kvs->end()) { - return ResultNcmContentMetaNotFound; - } - bool found_key = false; - - for (; entry != this->kvs->end(); entry++) { + for (auto entry = this->kvs->lower_bound(key); entry != this->kvs->end(); entry++) { if (entry->GetKey().id != key.id) { break; } @@ -183,31 +171,41 @@ namespace sts::ncm { return ResultSuccess; } - Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { + Result ContentMetaDatabaseInterface::EnsureEnabled() { if (this->disabled) { return ResultNcmInvalidContentMetaDatabase; } + return ResultSuccess; + } + + + Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { + R_DEBUG_START + R_TRY(this->EnsureEnabled()); + + D_LOG(" set title_id: 0x%lx\n", key.id); + D_LOG(" set version: 0x%x\n", key.version); + R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } - + R_DEBUG_START + R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } - + R_DEBUG_START + R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { @@ -217,45 +215,33 @@ namespace sts::ncm { return ResultSuccess; } - Result ContentMetaDatabaseInterface::ListContentInfo(Out out_entries_written, OutBuffer out_info, ContentMetaKey key, u32 start_index) { - if (start_index >> 0x1f != 0) { + Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { + R_DEBUG_START + if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_TRY(this->EnsureEnabled()); - const void* value = nullptr; + const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto header = GetValueHeader(value); const auto content_infos = GetValueContentInfos(value); - size_t entries_written = 0; - - if (out_info.num_elements == 0) { - out_entries_written.SetValue(0); - return ResultSuccess; + + size_t count; + for (count = 0; offset + count < header->content_count && count < out_info.num_elements; count++) { + out_info[count] = content_infos[offset + count]; } - for (size_t i = start_index; i < out_info.num_elements; i++) { - /* We have no more entries we can read out. */ - if (header->content_count <= start_index + i) { - break; - } - - out_info[i] = content_infos[i]; - entries_written = i + 1; - } - - out_entries_written.SetValue(entries_written); + out_count.SetValue(count); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; @@ -311,23 +297,22 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } - Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } - + Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START + R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; @@ -377,12 +362,12 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { out.SetValue(false); @@ -397,36 +382,26 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); - if (keys.num_elements == 0) { - out.SetValue(true); - return ResultSuccess; - } - - for (size_t i = 0; i < keys.num_elements; i++) { - bool has = false; + bool has = true; + for (size_t i = 0; i < keys.num_elements && has; i++) { R_TRY(this->Has(&has, keys[i])); - - if (!has) { - out.SetValue(false); - return ResultSuccess; - } } - out.SetValue(true); + out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { return ResultNcmContentMetaNotFound; @@ -439,12 +414,12 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { return ResultNcmInvalidContentMetaKey; @@ -459,34 +434,41 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } + D_LOG(" key title_id: 0x%lx\n", key.id); + D_LOG(" key version: 0x%x\n", key.version); + const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); + out_patch_id.SetValue(ext_header->patch_id); + D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { return ResultNcmBufferInsufficient; @@ -531,19 +513,20 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } - + R_DEBUG_START + R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { + R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -563,16 +546,16 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { + R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_TRY(this->EnsureEnabled()); const void* value = nullptr; size_t value_size = 0; @@ -598,12 +581,12 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); const void* value = nullptr; size_t value_size = 0; @@ -611,12 +594,12 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_DEBUG_START + R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { return ResultNcmInvalidContentMetaKey; @@ -628,13 +611,16 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -653,33 +639,28 @@ namespace sts::ncm { return ResultSuccess; } - Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId tid) { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START + R_TRY(this->EnsureEnabled()); + + const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); - ContentMetaKey key = {0}; - key.id = tid; - - if (this->kvs->GetCount() == 0) { - return ResultNcmContentMetaNotFound; - } - - auto entry = this->kvs->lower_bound(key); - if (entry == this->kvs->end() || entry->GetKey().id != key.id) { - return ResultNcmContentMetaNotFound; - } - - for (; entry != this->kvs->end(); entry++) { - if (entry->GetKey().id != key.id) { + std::optional found_key; + for (auto entry = this->kvs->lower_bound(key); entry != this->kvs->end(); entry++) { + if (entry->GetKey().id != title_id) { break; } - key = entry->GetKey(); + found_key = entry->GetKey(); } - *out_key = key; + if (!found_key) { + return ResultNcmContentMetaNotFound; + } + + *out_key = *found_key; return ResultSuccess; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { @@ -687,9 +668,7 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::Commit() { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } + R_TRY(this->EnsureEnabled()); return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp index b306631e3..d393b9d49 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -31,6 +31,8 @@ namespace sts::ncm { private: Result GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset); Result GetLatestContentMetaKeyImpl(ContentMetaKey* out_key, TitleId tid); + protected: + Result EnsureEnabled(); public: virtual Result Set(ContentMetaKey key, InBuffer value) override; virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value) override; diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 4369e0877..9e1599599 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,6 +20,8 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -95,15 +97,18 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -115,17 +120,21 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } return this->placeholder_accessor.Delete(placeholder_id); + R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -138,9 +147,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -173,9 +184,11 @@ namespace sts::ncm { this->placeholder_accessor.StoreToCache(f, placeholder_id); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START this->ClearContentCache(); if (this->disabled) { @@ -200,9 +213,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -220,9 +235,11 @@ namespace sts::ncm { } R_END_TRY_CATCH; return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -235,9 +252,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -248,9 +267,11 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -261,9 +282,11 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -281,9 +304,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -312,9 +337,11 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -337,9 +364,11 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -386,9 +415,11 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -403,16 +434,20 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -441,18 +476,22 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -475,9 +514,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -495,9 +536,11 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -556,9 +599,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -599,9 +644,11 @@ namespace sts::ncm { fflush(f); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); @@ -609,9 +656,11 @@ namespace sts::ncm { out_size.SetValue(st.f_bfree); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); @@ -619,14 +668,18 @@ namespace sts::ncm { out_size.SetValue(st.f_blocks); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -651,9 +704,11 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -682,9 +737,11 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -743,6 +800,7 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 3fecec315..908f13e43 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -180,7 +180,15 @@ namespace sts::ncm { return ResultSuccess; } - std::map g_mount_content_storage; + constexpr const char* SystemContentMountName = "@SystemContent"; + constexpr const char* UserContentMountName = "@UserContent"; + constexpr const char* SdCardContentMountName = "@SdCardContent"; + constexpr const char* GameCardMountNameBase = "@Gc"; + + constexpr const char* GameCardPartitionLetters[3] = { "U", "N", "S" }; + + /* Maps mount names to their common mount names. */ + std::map g_mount_content_storage; Result MountContentStorage(const char* mount_point, FsContentStorageId id) { if (!mount_point) { @@ -194,11 +202,30 @@ namespace sts::ncm { std::abort(); } - g_mount_content_storage[mount_point] = id; + switch (id) { + case FS_CONTENTSTORAGEID_NandSystem: + g_mount_content_storage[mount_point] = SystemContentMountName; + break; + + case FS_CONTENTSTORAGEID_NandUser: + g_mount_content_storage[mount_point] = UserContentMountName; + break; + + case FS_CONTENTSTORAGEID_SdCard: + g_mount_content_storage[mount_point] = SdCardContentMountName; + break; + + default: + std::abort(); + }; return ResultSuccess; } Result MountGameCardPartition(const char* mount_point, const FsGameCardHandle handle, FsGameCardPartiton partition) { + if (partition > 2) { + std::abort(); + } + FsFileSystem fs; R_TRY(fsOpenGameCardFileSystem(&fs, &handle, partition)); @@ -206,6 +233,9 @@ namespace sts::ncm { std::abort(); } + MountName mount = {0}; + snprintf(mount.name, sizeof(MountName), "%s%s%08x", GameCardMountNameBase, GameCardPartitionLetters[partition], handle.value); + g_mount_content_storage[mount_point] = mount.name; return ResultSuccess; } @@ -224,10 +254,6 @@ namespace sts::ncm { return ResultSuccess; } - constexpr const char* SystemContentMountName = "@SystemContent"; - constexpr const char* UserContentMountName = "@UserContent"; - constexpr const char* SdCardContentMountName = "@SdCardContent"; - Result ConvertToFsCommonPath(char* out_common_path, size_t out_len, const char* path) { if (!out_common_path || !path) { return ResultFsNullptrArgument; @@ -247,32 +273,14 @@ namespace sts::ncm { return ResultFsMountNameNotFound; } - FsContentStorageId content_storage_id = g_mount_content_storage[mount_name.name]; char translated_path[FS_MAX_PATH] = {0}; - const char* common_mount_name; - - switch (content_storage_id) { - case FS_CONTENTSTORAGEID_NandSystem: - common_mount_name = SystemContentMountName; - break; - - case FS_CONTENTSTORAGEID_NandUser: - common_mount_name = UserContentMountName; - break; - - case FS_CONTENTSTORAGEID_SdCard: - common_mount_name = SdCardContentMountName; - break; - - default: - std::abort(); - }; + std::string common_mount_name = g_mount_content_storage[mount_name.name]; if (fsdevTranslatePath(path, NULL, translated_path) == -1) { std::abort(); } - snprintf(out_common_path, out_len, "%s:%s", common_mount_name, translated_path); + snprintf(out_common_path, out_len, "%s:%s", common_mount_name.c_str(), translated_path); return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 2c450e540..787fb0988 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -27,7 +27,6 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x60000 #define INNER_HEAP_SIZE 0x100000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -45,10 +44,52 @@ extern "C" { sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Ncm; +namespace { + + /* Convenience definitions. */ + constexpr uintptr_t IramBase = 0x40000000ull; + constexpr uintptr_t IramPayloadBase = 0x40010000ull; + constexpr size_t IramSize = 0x40000; + constexpr size_t IramPayloadMaxSize = 0x2E000; + + /* Globals. */ + u8 __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; + + /* Helpers. */ + void ClearIram() { + /* Make page FFs. */ + memset(g_work_page, 0xFF, sizeof(g_work_page)); + + /* Overwrite all of IRAM with FFs. */ + for (size_t ofs = 0; ofs < IramSize; ofs += sizeof(g_work_page)) { + CopyToIram(IramBase + ofs, g_work_page, sizeof(g_work_page)); + } + } + + void DoReboot(AtmosphereFatalErrorContext *ctx) { + /* Ensure clean IRAM state. */ + ClearIram(); + + /* Copy in fatal error context, if relevant. */ + if (ctx != nullptr) { + std::memset(g_work_page, 0xCC, sizeof(g_work_page)); + std::memcpy(g_work_page, ctx, sizeof(*ctx)); + CopyToIram(IramPayloadBase + IramPayloadMaxSize, g_work_page, sizeof(g_work_page)); + } + + RebootToRcm(); + } + +} + void __libnx_exception_handler(ThreadExceptionDump *ctx) { StratosphereCrashHandler(ctx); } +void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) { + DoReboot(ctx); +} + void __libnx_initheap(void) { void* addr = nx_inner_heap; size_t size = nx_inner_heap_size; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index 246fa05b5..dc4484c63 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,9 +18,12 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" +#include "debug.hpp" + namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -34,37 +37,53 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -82,9 +101,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -104,29 +125,41 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -148,22 +181,30 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -201,13 +242,17 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -233,36 +278,51 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 98f4a81df..e7d649291 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -44,6 +44,7 @@ namespace sts::ncm { typedef Uuid PlaceHolderId; enum class ContentMetaType : u8 { + Unknown = 0x0, SystemProgram = 0x1, SystemData = 0x2, SystemUpdate = 0x3, @@ -107,29 +108,24 @@ namespace sts::ncm { } bool operator==(const ContentMetaKey& other) const { - if (this->id != other.id) { - return false; - } - - if (this->version != other.version) { - return false; - } - - if (this->type != other.type) { - return false; - } - - if (this->install_type != other.install_type) { - return false; - } - - return true; + return this->id == other.id && + this->version == other.version && + this->type == other.type && + this->install_type == other.install_type; } bool operator!=(const ContentMetaKey& other) const { return !(*this == other); } - } PACKED; + + static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type) { + return { .id = title_id, .version = version, .type = type }; + } + + static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type, ContentInstallType install_type) { + return { .id = title_id, .version = version, .type = type, .install_type = install_type }; + } + }; static_assert(sizeof(ContentMetaKey) == 0x10, "ContentMetaKey definition!"); @@ -139,14 +135,16 @@ namespace sts::ncm { struct ApplicationContentMetaKey { ContentMetaKey key; TitleId application_title_id; - } PACKED; + }; + + static_assert(sizeof(ApplicationContentMetaKey) == 0x18, "ApplicationContentMetaKey definition!"); struct ContentInfo { ContentId content_id; u8 size[6]; ContentType content_type; u8 id_offset; - } PACKED; + }; static_assert(sizeof(ContentInfo) == 0x18, "ContentInfo definition!"); From 9e9987a6737824e7eb75d269461eb6fbd2efd7ba Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sun, 4 Aug 2019 22:33:15 +1000 Subject: [PATCH 20/58] Fixed placeholder/content deletion --- .../ncm/source/impl/ncm_placeholder_accessor.cpp | 14 +++++++------- stratosphere/ncm/source/ncm_contentstorage.cpp | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index c3236a4c8..311fbc112 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -80,13 +80,13 @@ namespace sts::ncm::impl { this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - debug::DebugLog("Deleting %s\n", placeholder_path); - - R_TRY_CATCH(fsdevDeleteDirectoryRecursively(placeholder_path)) { - R_CATCH(ResultFsPathNotFound) { - return ResultNcmPlaceHolderNotFound; - } - } R_END_TRY_CATCH; + if (std::remove(placeholder_path) != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + } R_END_TRY_CATCH; + } return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 9e1599599..0c8ad80c2 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -223,16 +223,16 @@ namespace sts::ncm { } this->ClearContentCache(); - char content_path[FS_MAX_PATH] = {0}; - this->GetContentPath(content_path, content_id); - R_TRY_CATCH(fsdevDeleteDirectoryRecursively(content_path)) { - R_CATCH(ResultFsPathNotFound) { - return ResultNcmContentNotFound; - } - } R_END_TRY_CATCH; + if (std::remove(content_path) != 0) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmContentNotFound; + } + } R_END_TRY_CATCH; + } return ResultSuccess; R_DEBUG_END From f080f6793bc3669105f6b0957e8194c800c0b95d Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sun, 4 Aug 2019 23:39:54 +1000 Subject: [PATCH 21/58] Fixed incorrect content manager destruction --- .../ncm/source/impl/ncm_content_manager.cpp | 2 ++ .../ncm/source/impl/ncm_placeholder_accessor.cpp | 2 ++ .../ncm/source/lr_addoncontentlocationresolver.cpp | 8 ++++++++ .../ncm/source/lr_contentlocationresolver.cpp | 2 ++ .../ncm/source/lr_redirectonlylocationresolver.cpp | 14 ++++++++++++++ .../ncm/source/ncm_content_manager_service.cpp | 4 ---- .../ncm/source/ncm_content_manager_service.hpp | 2 -- .../ncm/source/ncm_contentmetadatabase.cpp | 7 ++++++- stratosphere/ncm/source/ncm_main.cpp | 4 ++++ 9 files changed, 38 insertions(+), 7 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index dcfe4326f..6d3d6af74 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -257,6 +257,8 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { + debug::DebugLog("Finalizing content manager...\n"); + { std::scoped_lock lk(g_mutex); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 311fbc112..60a424a1f 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -66,6 +66,7 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -80,6 +81,7 @@ namespace sts::ncm::impl { this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index a6051bdc9..4d4d5e1ef 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -24,6 +26,7 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -42,16 +45,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { + R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { + R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index ddbffc45e..0c5321ab5 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -48,6 +48,7 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; + debug::DebugLog("Resolved program path to %s\n", path.path); return ResultSuccess; R_DEBUG_END } @@ -107,6 +108,7 @@ namespace sts::lr { Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + debug::DebugLog("Redirected application html document path to %s\n", (*path.pointer).path); return ResultSuccess; R_DEBUG_END } diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 8f626f3ce..0c6ca239d 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -152,21 +152,28 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -182,21 +189,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index 80f82ae13..abfc6564e 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -21,10 +21,6 @@ namespace sts::ncm { - ContentManagerService::~ContentManagerService() { - impl::FinalizeContentManager(); - } - Result ContentManagerService::CreateContentStorage(StorageId storage_id) { R_DEBUG_START return impl::CreateContentStorage(storage_id); diff --git a/stratosphere/ncm/source/ncm_content_manager_service.hpp b/stratosphere/ncm/source/ncm_content_manager_service.hpp index 32e014125..6b6813158 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.hpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.hpp @@ -40,8 +40,6 @@ namespace sts::ncm { ActivateContentMetaDatabase = 11, InactivateContentMetaDatabase = 12, }; - public: - ~ContentManagerService(); public: virtual Result CreateContentStorage(StorageId storage_id); virtual Result CreateContentMetaDatabase(StorageId storage_id); diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 47c8d3ce3..4aca8bac1 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -209,10 +209,12 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { @@ -664,13 +666,16 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); - return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 787fb0988..2904a833c 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,6 +22,8 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + extern "C" { extern u32 __start__; @@ -160,6 +162,8 @@ int main(int argc, char **argv) s_content_manager_thread.Join(); s_location_resolver_thread.Join(); + + sts::ncm::impl::FinalizeContentManager(); return 0; } \ No newline at end of file From 6e5c0bde51d0ea49ed15d39bf41f593c91340ee2 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 14:13:15 +1000 Subject: [PATCH 22/58] Prevent automatic placeholder creation on open --- stratosphere/ncm/source/debug.cpp | 2 +- .../source/impl/ncm_placeholder_accessor.cpp | 7 +--- .../ncm/source/ncm_contentmetadatabase.cpp | 3 ++ .../ncm/source/ncm_contentstorage.cpp | 21 ++++------- stratosphere/ncm/source/ncm_fs.cpp | 37 +++++++++++++++++++ stratosphere/ncm/source/ncm_fs.hpp | 1 + .../ncm/source/ncm_readonlycontentstorage.cpp | 8 ++-- 7 files changed, 55 insertions(+), 24 deletions(-) diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp index 6659ae10f..2de47244b 100644 --- a/stratosphere/ncm/source/debug.cpp +++ b/stratosphere/ncm/source/debug.cpp @@ -23,7 +23,7 @@ namespace sts::debug { } size_t g_curr_log_offset = 0; - size_t g_log_skip = 4; + size_t g_log_skip = 1000; char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 60a424a1f..f209052fc 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -100,12 +100,9 @@ namespace sts::ncm::impl { char placeholder_path[FS_MAX_PATH] = {0}; this->GetPlaceHolderPath(placeholder_path, placeholder_id); - FILE* f = fopen(placeholder_path, "r+b"); - if (f == nullptr) { - debug::DebugLog("Failed to open placeholder %s\n", placeholder_path); - return fsdevGetLastResult(); - } + FILE* f = nullptr; + R_TRY(OpenFile(&f, placeholder_path, FS_OPEN_WRITE)); *out_handle = f; return ResultSuccess; diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 4aca8bac1..42110b74f 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -95,6 +95,8 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); + D_LOG("key: 0x%lx\n", key.id); + const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -384,6 +386,7 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + debug::DebugLog("Has 0x%lx\n", key.id); R_DEBUG_END } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 0c8ad80c2..6934dd65a 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -82,15 +82,12 @@ namespace sts::ncm { this->ClearContentCache(); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - this->content_cache_file_handle = fopen(content_path, "rb"); - if (this->content_cache_file_handle == NULL) { - R_TRY_CATCH(fsdevGetLastResult()) { - R_CATCH(ResultFsPathNotFound) { - return ResultNcmContentNotFound; - } - } R_END_TRY_CATCH; - } + R_TRY_CATCH(OpenFile(&this->content_cache_file_handle, content_path, FS_OPEN_READ)) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmContentNotFound; + } + } R_END_TRY_CATCH; this->cached_content_id = content_id; return ResultSuccess; @@ -624,15 +621,13 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - FILE* f = fopen(content_path, "r+b"); + FILE* f = nullptr; + R_TRY(OpenFile(&f, content_path, FS_OPEN_WRITE)); + ON_SCOPE_EXIT { fclose(f); }; - if (f == nullptr) { - return fsdevGetLastResult(); - } - if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 908f13e43..80b3c37a8 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -15,12 +15,49 @@ */ #include +#include +#include #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" namespace sts::ncm { + Result OpenFile(FILE** out, const char* path, u32 mode) { + bool has = false; + + /* Manually check if the file already exists, so it doesn't get created automatically. */ + R_TRY(HasFile(&has, path)); + if (!has) { + return ResultFsPathNotFound; + } + + const char* fopen_mode = ""; + + if (mode & FS_OPEN_APPEND) { + if (mode & FS_OPEN_READ) { + fopen_mode = "r+b"; + } else if (mode & FS_OPEN_WRITE) { + fopen_mode = "w+b"; + } + } else { + if (mode & FS_OPEN_READ) { + fopen_mode = "rb"; + } else if (mode & FS_OPEN_WRITE) { + fopen_mode = "wb"; + } + } + + FILE* f = fopen(path, fopen_mode); + + if (f == nullptr) { + return fsdevGetLastResult(); + } + + *out = f; + return ResultSuccess; + } + Result HasFile(bool* out, const char* path) { struct stat st; diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index 82cc6c5de..b5af99768 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -23,6 +23,7 @@ namespace sts::ncm { + Result OpenFile(FILE** out, const char* path, u32 mode); Result HasFile(bool* out, const char* path); Result HasDirectory(bool* out, const char* path); diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index dc4484c63..ef4c26452 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -224,14 +224,12 @@ namespace sts::ncm { path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); } - FILE* f = fopen(content_path, "rb"); + FILE* f = nullptr; + R_TRY(OpenFile(&f, content_path, FS_OPEN_READ)); + ON_SCOPE_EXIT { fclose(f); }; - - if (f == nullptr) { - return fsdevGetLastResult(); - } if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); From 4e75776112164129c705a13fef057168f41a1b59 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 18:31:46 +1000 Subject: [PATCH 23/58] Fixed List implementation. Also lots of debug logging. --- stratosphere/ncm/source/debug.cpp | 5 +++- .../ncm/source/lr_contentlocationresolver.cpp | 6 +++-- .../source/ncm_content_manager_service.cpp | 2 ++ .../ncm/source/ncm_contentmetadatabase.cpp | 27 ++++++++++++++++--- .../ncm/source/ncm_contentstorage.cpp | 9 +++++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp index 2de47244b..872802928 100644 --- a/stratosphere/ncm/source/debug.cpp +++ b/stratosphere/ncm/source/debug.cpp @@ -24,6 +24,7 @@ namespace sts::debug { size_t g_curr_log_offset = 0; size_t g_log_skip = 1000; + u32 g_page_num = 0; char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; @@ -94,8 +95,10 @@ namespace sts::debug { } g_log_skip--; - clear_iram(); g_curr_log_offset = 0; + g_page_num++; + clear_iram(); + CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); } /* Fill remainder with 0s. */ diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 0c5321ab5..8dd735cef 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -48,7 +48,7 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; - debug::DebugLog("Resolved program path to %s\n", path.path); + D_LOG("path: %s\n", path.path); return ResultSuccess; R_DEBUG_END } @@ -56,6 +56,7 @@ namespace sts::lr { Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; R_DEBUG_END } @@ -94,6 +95,7 @@ namespace sts::lr { R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; + D_LOG("path: %s\n", path.path); return ResultSuccess; R_DEBUG_END } @@ -108,7 +110,7 @@ namespace sts::lr { Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); - debug::DebugLog("Redirected application html document path to %s\n", (*path.pointer).path); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; R_DEBUG_END } diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index abfc6564e..b7c5acb11 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -47,6 +47,7 @@ namespace sts::ncm { Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); @@ -56,6 +57,7 @@ namespace sts::ncm { Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 42110b74f..f84076939 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -95,7 +95,10 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); - D_LOG("key: 0x%lx\n", key.id); + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version) + D_LOG("type: 0x%x\n", type); + D_LOG("id_offset: 0x%x\n", id_offset); const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { @@ -143,6 +146,9 @@ namespace sts::ncm { return ResultNcmContentNotFound; } + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, found_content_info->content_id); + D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -250,6 +256,12 @@ namespace sts::ncm { size_t entries_total = 0; size_t entries_written = 0; + D_LOG("app tid: 0x%x\n", application_title_id); + D_LOG("meta type: 0x%x\n", type); + D_LOG("install type: 0x%x\n", install_type); + D_LOG("tid min: 0x%lx\n", title_id_min); + D_LOG("tid max: 0x%lx\n", title_id_max); + /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -261,7 +273,7 @@ namespace sts::ncm { ContentMetaKey key = entry->GetKey(); /* Check if this entry matches the given filters. */ - if (!((static_cast(type) == 0 || key.type == type) && (title_id_min <= key.id && key.id <= title_id_max) && (key.install_type == ContentInstallType::Full || key.install_type == install_type))) { + if (!((static_cast(type) == 0 || key.type == type) && (title_id_min <= key.id && key.id <= title_id_max) && (key.install_type == ContentInstallType::Unknown || key.install_type == install_type))) { continue; } @@ -384,9 +396,11 @@ namespace sts::ncm { has = it->GetKey() == key; } + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version); + D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; - debug::DebugLog("Has 0x%lx\n", key.id); R_DEBUG_END } @@ -517,6 +531,13 @@ namespace sts::ncm { } } + for (size_t i = 0; i < content_ids.num_elements; i++) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, content_ids[i]); + D_LOG("content id: %s.nca\n", content_name); + D_LOG("orphaned: %d\n", out_orphaned[i]); + } + return ResultSuccess; R_DEBUG_END } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 6934dd65a..56941af67 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -263,6 +263,7 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; + D_LOG("path: %s\n", common_path); return ResultSuccess; R_DEBUG_END } @@ -410,6 +411,12 @@ namespace sts::ncm { return ResultSuccess; })); + for (size_t i = 0; i < entry_count; i++) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, out_buf[i]); + D_LOG("content id: %s.nca\n", content_name); + } + out_count.SetValue(static_cast(entry_count)); return ResultSuccess; R_DEBUG_END @@ -649,6 +656,7 @@ namespace sts::ncm { return fsdevGetLastResult(); } + D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; R_DEBUG_END @@ -661,6 +669,7 @@ namespace sts::ncm { return fsdevGetLastResult(); } + D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; R_DEBUG_END From d6ff261fcc8c1f26968e894b02c17a01a12ec98b Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 18:56:27 +1000 Subject: [PATCH 24/58] Removed debug code --- stratosphere/ncm/source/debug.cpp | 145 ------------------ stratosphere/ncm/source/debug.hpp | 39 ----- .../ncm/source/impl/ncm_content_manager.cpp | 6 - .../source/impl/ncm_placeholder_accessor.cpp | 4 - .../lr_addoncontentlocationresolver.cpp | 8 - .../ncm/source/lr_contentlocationresolver.cpp | 46 ------ .../ncm/source/lr_manager_service.cpp | 10 -- .../lr_redirectonlylocationresolver.cpp | 42 ----- .../source/lr_registeredlocationresolver.cpp | 20 --- .../source/ncm_content_manager_service.cpp | 30 ---- .../ncm/source/ncm_contentmetadatabase.cpp | 83 ---------- .../ncm/source/ncm_contentstorage.cpp | 67 -------- stratosphere/ncm/source/ncm_main.cpp | 2 - .../ncm/source/ncm_readonlycontentstorage.cpp | 60 -------- 14 files changed, 562 deletions(-) delete mode 100644 stratosphere/ncm/source/debug.cpp delete mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp deleted file mode 100644 index 872802928..000000000 --- a/stratosphere/ncm/source/debug.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include - -#include "impl/ncm_content_manager.hpp" -#include "debug.hpp" -#include "ncm_fs.hpp" - -namespace sts::debug { - - #define IRAM_BASE 0x40000000ull - #define IRAM_SIZE 0x40000 - - #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 - #define IRAM_PAYLOAD_BASE 0x40010000ull - - #define IRAM_SAFE_START 0x40038000ull - #define IRAM_SAFE_END 0x4003D000ull - #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START - - namespace { - - HosMutex g_log_mutex; - - } - - size_t g_curr_log_offset = 0; - size_t g_log_skip = 1000; - u32 g_page_num = 0; - - char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; - - void clear_iram(void) { - /* Fill with null*/ - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Overwrite all of our log's IRAM with 0s. */ - for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { - CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); - } - } - - void clear_log(void) { - std::scoped_lock lk(g_log_mutex); - - clear_iram(); - } - - Result Initialize() { - clear_log(); - return ResultSuccess; - } - - void DebugLog(const char* format, ...) { - std::scoped_lock lk(g_log_mutex); - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Format a string with our arguments. */ - va_list args; - va_start(args, format); - vsnprintf(g_work_page, 0x1000, format, args); - va_end(args); - - size_t msg_len = strnlen(g_work_page, 0x1000); - - /* Nothing to log. */ - if (msg_len == 0) { - return; - } - - /* Attempt to put some of our new string in the previous 4 bytes. */ - if (g_curr_log_offset >= 4) { - char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; - CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); - size_t prev_4_size = strnlen(prev_4, 4); - - /* Do we have room to put some of our new string in the old one? */ - if (prev_4_size < 4) { - size_t spare_4_space = 4 - prev_4_size; - memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); - - /* Copy the previous 4 bytes back. */ - CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); - memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); - /* Update our size again. */ - msg_len = strnlen(g_work_page, 0x1000); - } - } - - size_t msg_len_aligned = (msg_len + 3) & ~3; - - if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { - if (g_log_skip == 0) { - /* Log is full. Reboot to RCM to read it. */ - RebootToRcm(); - return; - } - - g_log_skip--; - g_curr_log_offset = 0; - g_page_num++; - clear_iram(); - CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); - } - - /* Fill remainder with 0s. */ - if (msg_len_aligned > msg_len) { - memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); - } - - uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; - uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); - - /* We are copying across two pages */ - if (iram_out_start + msg_len_aligned > iram_next_page) { - size_t first_page_size = iram_next_page - iram_out_start; - CopyToIram(iram_out_start, g_work_page, first_page_size); - CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); - } else { - CopyToIram(iram_out_start, g_work_page, msg_len_aligned); - } - - g_curr_log_offset += msg_len_aligned; - } - - void LogBytes(const void* buf, size_t len) { - if (buf == NULL || len == 0) { - return; - } - - const u8* bytes = static_cast(buf); - int count = 0; - DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); - DebugLog("-----------------------------------------------\n"); - - for (size_t i = 0; i < len; i++) { - DebugLog("%02x ", bytes[i]); - count++; - if ((count % 16) == 0) { - DebugLog("\n"); - } - } - - DebugLog("\n"); - } -} - diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp deleted file mode 100644 index 0eca28d9a..000000000 --- a/stratosphere/ncm/source/debug.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Adubbz - * - * 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 . - */ - -#pragma once -#include -#include -#include - -namespace sts::debug { - #define STR_(X) #X - #define STR(X) STR_(X) - - #define D_LOG(format, ...) \ - debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); - #define R_DEBUG_START \ - Result rc = [&]() -> Result { - #define R_DEBUG_END \ - }(); \ - D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ - return rc; - - Result Initialize(); - void DebugLog(const char* format, ...); - void LogBytes(const void* buf, size_t len); - -} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 6d3d6af74..7d403fb82 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,7 +19,6 @@ #include #include -#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -150,9 +149,6 @@ namespace sts::ncm::impl { if (g_initialized) { return ResultSuccess; } - - R_ASSERT(debug::Initialize()); - debug::DebugLog("ContentManager::InitializeContentManager\n"); size_t cur_storage_index = g_num_content_storage_entries; @@ -257,8 +253,6 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { - debug::DebugLog("Finalizing content manager...\n"); - { std::scoped_lock lk(g_mutex); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index f209052fc..9fe14696e 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,8 +20,6 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" -#include "../debug.hpp" - namespace sts::ncm::impl { unsigned int PlaceHolderAccessor::GetDirectoryDepth() { @@ -66,7 +64,6 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -81,7 +78,6 @@ namespace sts::ncm::impl { this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); - debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 4d4d5e1ef..a6051bdc9 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -26,7 +24,6 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -45,21 +42,16 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { - R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { - R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 8dd735cef..95680e8bd 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -48,21 +45,15 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -71,11 +62,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -84,39 +73,29 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -125,18 +104,14 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { - R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -151,57 +126,43 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -217,28 +178,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 82b11f7ec..6958cb11e 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -17,33 +17,23 @@ #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" -#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { - R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); - R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { - R_DEBUG_START - D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 0c6ca239d..b140e69b1 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -39,18 +36,14 @@ namespace sts::lr { } return ResultLrProgramNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -59,11 +52,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -72,31 +63,23 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START return ResultLrDataNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -105,75 +88,57 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { - R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -189,28 +154,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 1b5197fe8..a21c41120 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,8 +16,6 @@ #include "lr_registeredlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -32,7 +30,6 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -43,11 +40,9 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -56,26 +51,20 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -86,11 +75,9 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -99,30 +86,23 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { - R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index b7c5acb11..cd95b9191 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,94 +17,64 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ContentManagerService::CreateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index f84076939..976728b34 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,8 +17,6 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { namespace { @@ -95,11 +93,6 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version) - D_LOG("type: 0x%x\n", type); - D_LOG("id_offset: 0x%x\n", id_offset); - const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -146,9 +139,6 @@ namespace sts::ncm { return ResultNcmContentNotFound; } - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, found_content_info->content_id); - D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -189,50 +179,36 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - - D_LOG(" set title_id: 0x%lx\n", key.id); - D_LOG(" set version: 0x%x\n", key.version); - R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { - R_DEBUG_START if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } R_TRY(this->EnsureEnabled()); - const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -246,22 +222,14 @@ namespace sts::ncm { out_count.SetValue(count); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; - D_LOG("app tid: 0x%x\n", application_title_id); - D_LOG("meta type: 0x%x\n", type); - D_LOG("install type: 0x%x\n", install_type); - D_LOG("tid min: 0x%lx\n", title_id_min); - D_LOG("tid max: 0x%lx\n", title_id_max); - /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -313,21 +281,17 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; @@ -378,11 +342,9 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -396,16 +358,11 @@ namespace sts::ncm { has = it->GetKey() == key; } - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version); - D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); bool has = true; @@ -415,11 +372,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -433,11 +388,9 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { @@ -453,40 +406,30 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } - D_LOG(" key title_id: 0x%lx\n", key.id); - D_LOG(" key version: 0x%x\n", key.version); - const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); out_patch_id.SetValue(ext_header->patch_id); - D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { @@ -531,28 +474,17 @@ namespace sts::ncm { } } - for (size_t i = 0; i < content_ids.num_elements; i++) { - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, content_ids[i]); - D_LOG("content id: %s.nca\n", content_name); - D_LOG("orphaned: %d\n", out_orphaned[i]); - } - return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { - R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -572,11 +504,9 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { - R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -607,11 +537,9 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const void* value = nullptr; @@ -620,11 +548,9 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { @@ -637,16 +563,13 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -666,7 +589,6 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); @@ -686,20 +608,15 @@ namespace sts::ncm { *out_key = *found_key; return ResultSuccess; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 56941af67..0697f9df4 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,8 +20,6 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -94,18 +92,15 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -117,21 +112,17 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } return this->placeholder_accessor.Delete(placeholder_id); - R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -144,11 +135,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -181,11 +170,9 @@ namespace sts::ncm { this->placeholder_accessor.StoreToCache(f, placeholder_id); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START this->ClearContentCache(); if (this->disabled) { @@ -210,11 +197,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -232,11 +217,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -249,11 +232,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -263,13 +244,10 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; - D_LOG("path: %s\n", common_path); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -280,11 +258,9 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -302,11 +278,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -335,11 +309,9 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -362,11 +334,9 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -411,19 +381,11 @@ namespace sts::ncm { return ResultSuccess; })); - for (size_t i = 0; i < entry_count; i++) { - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, out_buf[i]); - D_LOG("content id: %s.nca\n", content_name); - } - out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -438,20 +400,16 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -480,22 +438,18 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -518,11 +472,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -540,11 +492,9 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -603,11 +553,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -646,44 +594,34 @@ namespace sts::ncm { fflush(f); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -708,11 +646,9 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -741,11 +677,9 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -804,7 +738,6 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 2904a833c..14ccc2617 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,8 +22,6 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - extern "C" { extern u32 __start__; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index ef4c26452..b02cefc93 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,12 +18,9 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -37,53 +34,37 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -101,11 +82,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -125,41 +104,29 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -181,30 +148,22 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -240,17 +199,13 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -276,51 +231,36 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } } \ No newline at end of file From 7bcf2276a751461c5aaf07cef28fbb60bfbca56c Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 19:16:27 +1000 Subject: [PATCH 25/58] Added a scope guard for WritePlaceHolder --- stratosphere/ncm/source/ncm_contentstorage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 0697f9df4..96de686db 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -155,6 +155,8 @@ namespace sts::ncm { } } R_END_TRY_CATCH; + auto file_guard = SCOPE_GUARD { fclose(f); }; + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -168,7 +170,7 @@ namespace sts::ncm { } this->placeholder_accessor.StoreToCache(f, placeholder_id); - + file_guard.Cancel(); return ResultSuccess; } From 5e0f4130c4e1e53b9f62bcace63bb11347483d7e Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 21:29:28 +1000 Subject: [PATCH 26/58] Manually prevent placeholder/content appending --- stratosphere/ncm/source/ncm_contentstorage.cpp | 16 ++++++++++++++++ stratosphere/ncm/source/ncm_fs.cpp | 2 +- stratosphere/ncm/source/ncm_types.hpp | 14 ++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 96de686db..317ab6a68 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -157,6 +157,14 @@ namespace sts::ncm { auto file_guard = SCOPE_GUARD { fclose(f); }; + u64 size = 0; + R_TRY(GetSizeFromPlaceHolderId(&size, placeholder_id)); + + /* We can't disable append with stdio, so check this manually. */ + if (offset + data.num_elements > size) { + return ResultFileExtensionWithoutOpenModeAllowAppend; + } + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -585,6 +593,14 @@ namespace sts::ncm { fclose(f); }; + u64 size = 0; + R_TRY(GetSizeFromContentId(&size, content_id)); + + /* We can't disable append with stdio, so check this manually. */ + if (offset + data.num_elements > size) { + return ResultFileExtensionWithoutOpenModeAllowAppend; + } + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 80b3c37a8..4f675b3d3 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -301,7 +301,7 @@ namespace sts::ncm { /* We should be given a qualified path. */ if (!unqual_path || unqual_path > path + 0xf) { - return ResultFsUnqualifiedPath; + return ResultInvalidMountName; } strncpy(mount_name.name, path, unqual_path - path); diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index e7d649291..587e59404 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -152,11 +152,13 @@ namespace sts::ncm { typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); // TODO: Move to libstrat - static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); - static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); - static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); - static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); - static constexpr Result ResultFsUnqualifiedPath = MAKERESULT(Module_Fs, 6065); - static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); + static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); + static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); + static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); + static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); + + static constexpr Result ResultFileExtensionWithoutOpenModeAllowAppend = MAKERESULT(Module_Fs, 6201); + static constexpr Result ResultInvalidMountName = MAKERESULT(Module_Fs, 6065); + static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); } \ No newline at end of file From dac951f72b86b493539652142a8740b01415a3f1 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 21:32:28 +1000 Subject: [PATCH 27/58] Revert "Removed debug code" This reverts commit d6ff261fcc8c1f26968e894b02c17a01a12ec98b. --- stratosphere/ncm/source/debug.cpp | 145 ++++++++++++++++++ stratosphere/ncm/source/debug.hpp | 39 +++++ .../ncm/source/impl/ncm_content_manager.cpp | 6 + .../source/impl/ncm_placeholder_accessor.cpp | 4 + .../lr_addoncontentlocationresolver.cpp | 8 + .../ncm/source/lr_contentlocationresolver.cpp | 46 ++++++ .../ncm/source/lr_manager_service.cpp | 10 ++ .../lr_redirectonlylocationresolver.cpp | 42 +++++ .../source/lr_registeredlocationresolver.cpp | 20 +++ .../source/ncm_content_manager_service.cpp | 30 ++++ .../ncm/source/ncm_contentmetadatabase.cpp | 83 ++++++++++ .../ncm/source/ncm_contentstorage.cpp | 67 ++++++++ stratosphere/ncm/source/ncm_main.cpp | 2 + .../ncm/source/ncm_readonlycontentstorage.cpp | 60 ++++++++ 14 files changed, 562 insertions(+) create mode 100644 stratosphere/ncm/source/debug.cpp create mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp new file mode 100644 index 000000000..872802928 --- /dev/null +++ b/stratosphere/ncm/source/debug.cpp @@ -0,0 +1,145 @@ +#include + +#include "impl/ncm_content_manager.hpp" +#include "debug.hpp" +#include "ncm_fs.hpp" + +namespace sts::debug { + + #define IRAM_BASE 0x40000000ull + #define IRAM_SIZE 0x40000 + + #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 + #define IRAM_PAYLOAD_BASE 0x40010000ull + + #define IRAM_SAFE_START 0x40038000ull + #define IRAM_SAFE_END 0x4003D000ull + #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START + + namespace { + + HosMutex g_log_mutex; + + } + + size_t g_curr_log_offset = 0; + size_t g_log_skip = 1000; + u32 g_page_num = 0; + + char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; + + void clear_iram(void) { + /* Fill with null*/ + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Overwrite all of our log's IRAM with 0s. */ + for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); + } + } + + void clear_log(void) { + std::scoped_lock lk(g_log_mutex); + + clear_iram(); + } + + Result Initialize() { + clear_log(); + return ResultSuccess; + } + + void DebugLog(const char* format, ...) { + std::scoped_lock lk(g_log_mutex); + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Format a string with our arguments. */ + va_list args; + va_start(args, format); + vsnprintf(g_work_page, 0x1000, format, args); + va_end(args); + + size_t msg_len = strnlen(g_work_page, 0x1000); + + /* Nothing to log. */ + if (msg_len == 0) { + return; + } + + /* Attempt to put some of our new string in the previous 4 bytes. */ + if (g_curr_log_offset >= 4) { + char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; + CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); + size_t prev_4_size = strnlen(prev_4, 4); + + /* Do we have room to put some of our new string in the old one? */ + if (prev_4_size < 4) { + size_t spare_4_space = 4 - prev_4_size; + memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); + + /* Copy the previous 4 bytes back. */ + CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); + memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); + /* Update our size again. */ + msg_len = strnlen(g_work_page, 0x1000); + } + } + + size_t msg_len_aligned = (msg_len + 3) & ~3; + + if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { + if (g_log_skip == 0) { + /* Log is full. Reboot to RCM to read it. */ + RebootToRcm(); + return; + } + + g_log_skip--; + g_curr_log_offset = 0; + g_page_num++; + clear_iram(); + CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); + } + + /* Fill remainder with 0s. */ + if (msg_len_aligned > msg_len) { + memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); + } + + uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; + uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); + + /* We are copying across two pages */ + if (iram_out_start + msg_len_aligned > iram_next_page) { + size_t first_page_size = iram_next_page - iram_out_start; + CopyToIram(iram_out_start, g_work_page, first_page_size); + CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); + } else { + CopyToIram(iram_out_start, g_work_page, msg_len_aligned); + } + + g_curr_log_offset += msg_len_aligned; + } + + void LogBytes(const void* buf, size_t len) { + if (buf == NULL || len == 0) { + return; + } + + const u8* bytes = static_cast(buf); + int count = 0; + DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); + DebugLog("-----------------------------------------------\n"); + + for (size_t i = 0; i < len; i++) { + DebugLog("%02x ", bytes[i]); + count++; + if ((count % 16) == 0) { + DebugLog("\n"); + } + } + + DebugLog("\n"); + } +} + diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp new file mode 100644 index 000000000..0eca28d9a --- /dev/null +++ b/stratosphere/ncm/source/debug.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +namespace sts::debug { + #define STR_(X) #X + #define STR(X) STR_(X) + + #define D_LOG(format, ...) \ + debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); + #define R_DEBUG_START \ + Result rc = [&]() -> Result { + #define R_DEBUG_END \ + }(); \ + D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ + return rc; + + Result Initialize(); + void DebugLog(const char* format, ...); + void LogBytes(const void* buf, size_t len); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 7d403fb82..6d3d6af74 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,6 +19,7 @@ #include #include +#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -149,6 +150,9 @@ namespace sts::ncm::impl { if (g_initialized) { return ResultSuccess; } + + R_ASSERT(debug::Initialize()); + debug::DebugLog("ContentManager::InitializeContentManager\n"); size_t cur_storage_index = g_num_content_storage_entries; @@ -253,6 +257,8 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { + debug::DebugLog("Finalizing content manager...\n"); + { std::scoped_lock lk(g_mutex); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 9fe14696e..f209052fc 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,6 +20,8 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" +#include "../debug.hpp" + namespace sts::ncm::impl { unsigned int PlaceHolderAccessor::GetDirectoryDepth() { @@ -64,6 +66,7 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -78,6 +81,7 @@ namespace sts::ncm::impl { this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index a6051bdc9..4d4d5e1ef 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -24,6 +26,7 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -42,16 +45,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { + R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { + R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 95680e8bd..8dd735cef 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -45,15 +48,21 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; + D_LOG("path: %s\n", path.path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -62,9 +71,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -73,29 +84,39 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; + D_LOG("path: %s\n", path.path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -104,14 +125,18 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { + R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -126,43 +151,57 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -178,21 +217,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 6958cb11e..82b11f7ec 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -17,23 +17,33 @@ #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" +#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { + R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); + R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { + R_DEBUG_START + D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index b140e69b1..0c6ca239d 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -36,14 +39,18 @@ namespace sts::lr { } return ResultLrProgramNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -52,9 +59,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -63,23 +72,31 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START return ResultLrDataNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -88,57 +105,75 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { + R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -154,21 +189,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index a21c41120..1b5197fe8 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,6 +16,8 @@ #include "lr_registeredlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -30,6 +32,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -40,9 +43,11 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -51,20 +56,26 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -75,9 +86,11 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -86,23 +99,30 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { + R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index cd95b9191..b7c5acb11 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,64 +17,94 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + namespace sts::ncm { Result ContentManagerService::CreateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { + R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { + R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 976728b34..f84076939 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,6 +17,8 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { namespace { @@ -93,6 +95,11 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version) + D_LOG("type: 0x%x\n", type); + D_LOG("id_offset: 0x%x\n", id_offset); + const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -139,6 +146,9 @@ namespace sts::ncm { return ResultNcmContentNotFound; } + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, found_content_info->content_id); + D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -179,36 +189,50 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); + + D_LOG(" set title_id: 0x%lx\n", key.id); + D_LOG(" set version: 0x%x\n", key.version); + R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { + R_DEBUG_START if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } R_TRY(this->EnsureEnabled()); + const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -222,14 +246,22 @@ namespace sts::ncm { out_count.SetValue(count); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; + D_LOG("app tid: 0x%x\n", application_title_id); + D_LOG("meta type: 0x%x\n", type); + D_LOG("install type: 0x%x\n", install_type); + D_LOG("tid min: 0x%lx\n", title_id_min); + D_LOG("tid max: 0x%lx\n", title_id_max); + /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -281,17 +313,21 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; @@ -342,9 +378,11 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -358,11 +396,16 @@ namespace sts::ncm { has = it->GetKey() == key; } + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version); + D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); bool has = true; @@ -372,9 +415,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -388,9 +433,11 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { @@ -406,30 +453,40 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } + D_LOG(" key title_id: 0x%lx\n", key.id); + D_LOG(" key version: 0x%x\n", key.version); + const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); out_patch_id.SetValue(ext_header->patch_id); + D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { @@ -474,17 +531,28 @@ namespace sts::ncm { } } + for (size_t i = 0; i < content_ids.num_elements; i++) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, content_ids[i]); + D_LOG("content id: %s.nca\n", content_name); + D_LOG("orphaned: %d\n", out_orphaned[i]); + } + return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { + R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -504,9 +572,11 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { + R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -537,9 +607,11 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); const void* value = nullptr; @@ -548,9 +620,11 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { @@ -563,13 +637,16 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -589,6 +666,7 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); @@ -608,15 +686,20 @@ namespace sts::ncm { *out_key = *found_key; return ResultSuccess; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 317ab6a68..99106648a 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,6 +20,8 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -92,15 +94,18 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -112,17 +117,21 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } return this->placeholder_accessor.Delete(placeholder_id); + R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -135,9 +144,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -180,9 +191,11 @@ namespace sts::ncm { this->placeholder_accessor.StoreToCache(f, placeholder_id); file_guard.Cancel(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START this->ClearContentCache(); if (this->disabled) { @@ -207,9 +220,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -227,9 +242,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -242,9 +259,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -254,10 +273,13 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; + D_LOG("path: %s\n", common_path); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -268,9 +290,11 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -288,9 +312,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -319,9 +345,11 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -344,9 +372,11 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -391,11 +421,19 @@ namespace sts::ncm { return ResultSuccess; })); + for (size_t i = 0; i < entry_count; i++) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, out_buf[i]); + D_LOG("content id: %s.nca\n", content_name); + } + out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -410,16 +448,20 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -448,18 +490,22 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -482,9 +528,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -502,9 +550,11 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -563,9 +613,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -612,34 +664,44 @@ namespace sts::ncm { fflush(f); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } + D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } + D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START this->placeholder_accessor.ClearAllCaches(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -664,9 +726,11 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -695,9 +759,11 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -756,6 +822,7 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 14ccc2617..2904a833c 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,6 +22,8 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + extern "C" { extern u32 __start__; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index b02cefc93..ef4c26452 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,9 +18,12 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" +#include "debug.hpp" + namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -34,37 +37,53 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -82,9 +101,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -104,29 +125,41 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -148,22 +181,30 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -199,13 +240,17 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START if (this->disabled) { return ResultNcmInvalidContentStorage; } @@ -231,36 +276,51 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } } \ No newline at end of file From cf06cb7628d58ba4397ca22de01615ebb3ff8f51 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 6 Aug 2019 22:13:05 +1000 Subject: [PATCH 28/58] Always cache placeholder file. Switch to ftell for preventing appending --- stratosphere/ncm/source/ncm_contentstorage.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 99106648a..80f57919a 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -166,10 +166,14 @@ namespace sts::ncm { } } R_END_TRY_CATCH; - auto file_guard = SCOPE_GUARD { fclose(f); }; + ON_SCOPE_EXIT { + this->placeholder_accessor.StoreToCache(f, placeholder_id); + }; - u64 size = 0; - R_TRY(GetSizeFromPlaceHolderId(&size, placeholder_id)); + if (fseek(f, 0, SEEK_END) != 0) { + return fsdevGetLastResult(); + } + u64 size = ftell(f); /* We can't disable append with stdio, so check this manually. */ if (offset + data.num_elements > size) { @@ -188,8 +192,6 @@ namespace sts::ncm { fflush(f); } - this->placeholder_accessor.StoreToCache(f, placeholder_id); - file_guard.Cancel(); return ResultSuccess; R_DEBUG_END } @@ -645,8 +647,10 @@ namespace sts::ncm { fclose(f); }; - u64 size = 0; - R_TRY(GetSizeFromContentId(&size, content_id)); + if (fseek(f, 0, SEEK_END) != 0) { + return fsdevGetLastResult(); + } + u64 size = ftell(f); /* We can't disable append with stdio, so check this manually. */ if (offset + data.num_elements > size) { From fac8acebba63b56721d84f7e2ece3d01abc8a7ca Mon Sep 17 00:00:00 2001 From: Adubbz Date: Wed, 7 Aug 2019 18:48:31 +1000 Subject: [PATCH 29/58] Universally use EnsureEnabled --- .../ncm/source/ncm_contentmetadatabase.cpp | 9 -- .../ncm/source/ncm_contentmetadatabase.hpp | 2 - .../ncm/source/ncm_contentstorage.cpp | 98 +++++-------------- .../ncm/source/ncm_icontentmetadatabase.cpp | 8 ++ .../ncm/source/ncm_icontentmetadatabase.hpp | 2 + .../ncm/source/ncm_icontentstorage.cpp | 8 ++ .../ncm/source/ncm_icontentstorage.hpp | 2 + .../ncm/source/ncm_readonlycontentstorage.cpp | 24 ++--- 8 files changed, 50 insertions(+), 103 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index f84076939..5c0478373 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -179,15 +179,6 @@ namespace sts::ncm { return ResultSuccess; } - Result ContentMetaDatabaseInterface::EnsureEnabled() { - if (this->disabled) { - return ResultNcmInvalidContentMetaDatabase; - } - - return ResultSuccess; - } - - Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { R_DEBUG_START R_TRY(this->EnsureEnabled()); diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp index d393b9d49..b306631e3 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -31,8 +31,6 @@ namespace sts::ncm { private: Result GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset); Result GetLatestContentMetaKeyImpl(ContentMetaKey* out_key, TitleId tid); - protected: - Result EnsureEnabled(); public: virtual Result Set(ContentMetaKey key, InBuffer value) override; virtual Result Get(Out out_size, ContentMetaKey key, OutBuffer out_value) override; diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 80f57919a..3b0695795 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -29,10 +29,7 @@ namespace sts::ncm { } Result ContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush) { - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } - + R_TRY(this->EnsureEnabled()); R_TRY(CheckContentStorageDirectoriesExist(root_path)); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -95,9 +92,7 @@ namespace sts::ncm { Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; @@ -106,9 +101,7 @@ namespace sts::ncm { Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); @@ -122,9 +115,7 @@ namespace sts::ncm { Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); return this->placeholder_accessor.Delete(placeholder_id); R_DEBUG_END @@ -132,9 +123,7 @@ namespace sts::ncm { Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPlaceHolderPath(placeholder_path, placeholder_id); @@ -154,9 +143,7 @@ namespace sts::ncm { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); FILE* f = nullptr; @@ -199,10 +186,7 @@ namespace sts::ncm { Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { R_DEBUG_START this->ClearContentCache(); - - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; char content_path[FS_MAX_PATH] = {0}; @@ -227,9 +211,7 @@ namespace sts::ncm { Result ContentStorageInterface::Delete(ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); this->ClearContentCache(); char content_path[FS_MAX_PATH] = {0}; @@ -249,9 +231,7 @@ namespace sts::ncm { Result ContentStorageInterface::Has(Out out, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); @@ -266,9 +246,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; @@ -282,9 +260,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; @@ -297,9 +273,7 @@ namespace sts::ncm { Result ContentStorageInterface::CleanupAllPlaceHolder() { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.ClearAllCaches(); @@ -319,9 +293,7 @@ namespace sts::ncm { Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); @@ -352,9 +324,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetContentCount(Out out_count) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); @@ -383,9 +353,7 @@ namespace sts::ncm { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); @@ -436,9 +404,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); @@ -464,9 +430,7 @@ namespace sts::ncm { Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char old_content_path[FS_MAX_PATH] = {0}; char new_content_path[FS_MAX_PATH] = {0}; @@ -497,9 +461,7 @@ namespace sts::ncm { Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; @@ -513,9 +475,7 @@ namespace sts::ncm { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); @@ -535,9 +495,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; u8 key_generation = 0; @@ -557,9 +515,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -625,9 +581,7 @@ namespace sts::ncm { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); bool is_development = false; @@ -706,9 +660,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); bool found_in_cache = false; size_t size = 0; @@ -768,9 +720,7 @@ namespace sts::ncm { Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp index 7512ccc15..155b21103 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp @@ -18,6 +18,14 @@ namespace sts::ncm { + Result IContentMetaDatabase::EnsureEnabled() { + if (this->disabled) { + return ResultNcmInvalidContentMetaDatabase; + } + + return ResultSuccess; + } + Result IContentMetaDatabase::Set(ContentMetaKey key, InBuffer value) { std::abort(); } diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp index 4a9855f91..627e0b839 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -52,6 +52,8 @@ namespace sts::ncm { sts::kvdb::MemoryKeyValueStore* kvs; char mount_name[16]; bool disabled; + protected: + Result EnsureEnabled(); public: IContentMetaDatabase(sts::kvdb::MemoryKeyValueStore* kvs) : kvs(kvs), disabled(false) diff --git a/stratosphere/ncm/source/ncm_icontentstorage.cpp b/stratosphere/ncm/source/ncm_icontentstorage.cpp index 26db32fc5..8eef3d2d3 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.cpp @@ -18,6 +18,14 @@ namespace sts::ncm { + Result IContentStorage::EnsureEnabled() { + if (this->disabled) { + return ResultNcmInvalidContentStorage; + } + + return ResultSuccess; + } + Result IContentStorage::GeneratePlaceHolderId(Out out) { std::abort(); } diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index 6e58ea6c6..3e1d1d1f6 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -59,6 +59,8 @@ namespace sts::ncm { char root_path[FS_MAX_PATH-1]; MakeContentPathFunc make_content_path_func; bool disabled; + protected: + Result EnsureEnabled(); public: virtual Result GeneratePlaceHolderId(Out out); virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size); diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index ef4c26452..63f893f98 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -24,9 +24,7 @@ namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -84,9 +82,7 @@ namespace sts::ncm { Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; this->make_content_path_func(content_path, content_id, this->root_path); @@ -106,9 +102,7 @@ namespace sts::ncm { Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; @@ -160,9 +154,7 @@ namespace sts::ncm { Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; bool is_content_file = false; @@ -210,9 +202,7 @@ namespace sts::ncm { return ResultNcmInvalidOffset; } - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; bool is_content_file = false; @@ -251,9 +241,7 @@ namespace sts::ncm { Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { R_DEBUG_START - if (this->disabled) { - return ResultNcmInvalidContentStorage; - } + R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; u8 key_generation = 0; From 7dce15bcda3d7fc090443dfaffe67459377271a5 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Wed, 7 Aug 2019 20:43:48 +1000 Subject: [PATCH 30/58] Abstract away file writing logic --- .../ncm/source/ncm_contentstorage.cpp | 42 +------------------ stratosphere/ncm/source/ncm_fs.cpp | 22 ++++++++++ stratosphere/ncm/source/ncm_fs.hpp | 2 + 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 3b0695795..b62f792ed 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -157,27 +157,7 @@ namespace sts::ncm { this->placeholder_accessor.StoreToCache(f, placeholder_id); }; - if (fseek(f, 0, SEEK_END) != 0) { - return fsdevGetLastResult(); - } - u64 size = ftell(f); - - /* We can't disable append with stdio, so check this manually. */ - if (offset + data.num_elements > size) { - return ResultFileExtensionWithoutOpenModeAllowAppend; - } - - if (fseek(f, offset, SEEK_SET) != 0) { - return fsdevGetLastResult(); - } - - if (fwrite(data.buffer, sizeof(u8), data.num_elements, f) != data.num_elements) { - return fsdevGetLastResult(); - } - - if (!this->placeholder_accessor.delay_flush) { - fflush(f); - } + R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, !this->placeholder_accessor.delay_flush)); return ResultSuccess; R_DEBUG_END @@ -601,25 +581,7 @@ namespace sts::ncm { fclose(f); }; - if (fseek(f, 0, SEEK_END) != 0) { - return fsdevGetLastResult(); - } - u64 size = ftell(f); - - /* We can't disable append with stdio, so check this manually. */ - if (offset + data.num_elements > size) { - return ResultFileExtensionWithoutOpenModeAllowAppend; - } - - if (fseek(f, offset, SEEK_SET) != 0) { - return fsdevGetLastResult(); - } - - if (fwrite(data.buffer, sizeof(u8), data.num_elements, f) != data.num_elements) { - return fsdevGetLastResult(); - } - - fflush(f); + R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); return ResultSuccess; R_DEBUG_END diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 4f675b3d3..6a5616aa1 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -21,6 +21,8 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode) { @@ -58,6 +60,26 @@ namespace sts::ncm { return ResultSuccess; } + Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option) { + R_DEBUG_START + D_LOG("Writing 0x%llx to offset 0x%llx\n", size, offset); + + if (fseek(f, offset, SEEK_SET) != 0) { + return fsdevGetLastResult(); + } + + if (fwrite(buffer, size, 1, f) != 1) { + return fsdevGetLastResult(); + } + + if (option & FS_WRITEOPTION_FLUSH) { + fflush(f); + } + + return ResultSuccess; + R_DEBUG_END + } + Result HasFile(bool* out, const char* path) { struct stat st; diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index b5af99768..335580d48 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -24,6 +24,8 @@ namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode); + Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option); + Result HasFile(bool* out, const char* path); Result HasDirectory(bool* out, const char* path); From e528269b532b8fb0afb94259c1ca0d4364968deb Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 8 Aug 2019 16:42:25 +1000 Subject: [PATCH 31/58] Misc cleanup --- .../ncm/source/ncm_contentstorage.cpp | 10 +----- stratosphere/ncm/source/ncm_fs.cpp | 35 ++++++++++++++----- stratosphere/ncm/source/ncm_fs.hpp | 3 ++ .../ncm/source/ncm_readonlycontentstorage.cpp | 8 +---- stratosphere/ncm/source/ncm_types.hpp | 14 ++++---- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index b62f792ed..3a698a9ba 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -456,18 +456,10 @@ namespace sts::ncm { } R_TRY(this->EnsureEnabled()); - char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); R_TRY(this->OpenCachedContentFile(content_id)); - - if (fseek(this->content_cache_file_handle, offset, SEEK_SET) != 0) { - return fsdevGetLastResult(); - } - - if (fread(buf.buffer, 1, buf.num_elements, this->content_cache_file_handle) != buf.num_elements && ferror(this->content_cache_file_handle)) { - return fsdevGetLastResult(); - } + R_TRY(ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); return ResultSuccess; R_DEBUG_END diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 6a5616aa1..03a1941b8 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -68,7 +68,7 @@ namespace sts::ncm { return fsdevGetLastResult(); } - if (fwrite(buffer, size, 1, f) != 1) { + if (fwrite(buffer, 1, size, f) != size) { return fsdevGetLastResult(); } @@ -80,6 +80,18 @@ namespace sts::ncm { R_DEBUG_END } + Result ReadFile(FILE* f, size_t offset, void* buffer, size_t size) { + if (fseek(f, offset, SEEK_SET) != 0) { + return fsdevGetLastResult(); + } + + if (fread(buffer, 1, size, f) != size && ferror(f)) { + return fsdevGetLastResult(); + } + + return ResultSuccess; + } + Result HasFile(bool* out, const char* path) { struct stat st; @@ -219,6 +231,18 @@ namespace sts::ncm { return mount_name; } + Result GetMountNameFromPath(MountName* mount_name, const char* path) { + const char* unqual_path = strchr(path, ':'); + + /* We should be given a qualified path. */ + if (!unqual_path || unqual_path > path + 0xf) { + return ResultFsInvalidMountName; + } + + strncpy(mount_name->name, path, unqual_path - path); + return ResultSuccess; + } + Result MountSystemSaveData(const char* mount_point, FsSaveDataSpaceId space_id, u64 save_id) { if (!mount_point) { return ResultFsNullptrArgument; @@ -319,14 +343,7 @@ namespace sts::ncm { } MountName mount_name = {0}; - const char* unqual_path = strchr(path, ':'); - - /* We should be given a qualified path. */ - if (!unqual_path || unqual_path > path + 0xf) { - return ResultInvalidMountName; - } - - strncpy(mount_name.name, path, unqual_path - path); + R_TRY(GetMountNameFromPath(&mount_name, path)); if (!fsdevGetDeviceFileSystem(mount_name.name) || g_mount_content_storage.find(mount_name.name) == g_mount_content_storage.end()) { return ResultFsMountNameNotFound; diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index 335580d48..4e857406d 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -25,6 +25,7 @@ namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode); Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option); + Result ReadFile(FILE* f, size_t offset, void* buffer, size_t size); Result HasFile(bool* out, const char* path); Result HasDirectory(bool* out, const char* path); @@ -40,6 +41,8 @@ namespace sts::ncm { Result GetGameCardHandle(FsGameCardHandle* out_handle); MountName CreateUniqueMountName(); + Result GetMountNameFromPath(MountName* mount_name, const char* path); + Result MountSystemSaveData(const char* mount_point, FsSaveDataSpaceId space_id, u64 save_id); Result MountContentStorage(const char* mount_point, FsContentStorageId id); Result MountGameCardPartition(const char* mount_point, const FsGameCardHandle handle, FsGameCardPartiton partition); diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index 63f893f98..b70b36d7d 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -221,13 +221,7 @@ namespace sts::ncm { fclose(f); }; - if (fseek(f, offset, SEEK_SET) != 0) { - return fsdevGetLastResult(); - } - - if (fread(buf.buffer, 1, buf.num_elements, f) != buf.num_elements && ferror(f)) { - return fsdevGetLastResult(); - } + R_TRY(ReadFile(f, offset, buf.buffer, buf.num_elements)); return ResultSuccess; R_DEBUG_END diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 587e59404..17c0b5d00 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -152,13 +152,13 @@ namespace sts::ncm { typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); // TODO: Move to libstrat - static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); - static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); - static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); - static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); + static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); + static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); + static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); + static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); - static constexpr Result ResultFileExtensionWithoutOpenModeAllowAppend = MAKERESULT(Module_Fs, 6201); - static constexpr Result ResultInvalidMountName = MAKERESULT(Module_Fs, 6065); - static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); + static constexpr Result ResultFsFileExtensionWithoutOpenModeAllowAppend = MAKERESULT(Module_Fs, 6201); + static constexpr Result ResultFsInvalidMountName = MAKERESULT(Module_Fs, 6065); + static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); } \ No newline at end of file From 1aa4c12e5e3cf92642ec2142dd037ae38bca7338 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 8 Aug 2019 18:07:51 +1000 Subject: [PATCH 32/58] Refactor placeholder cacheing --- .../source/impl/ncm_placeholder_accessor.cpp | 208 +++++++++--------- .../source/impl/ncm_placeholder_accessor.hpp | 33 +-- .../ncm/source/ncm_contentstorage.cpp | 50 ++--- 3 files changed, 142 insertions(+), 149 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index f209052fc..ba3a8249f 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -24,6 +24,87 @@ namespace sts::ncm::impl { + Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { + if (this->LoadFromCache(out_handle, placeholder_id)) { + return ResultSuccess; + } + char placeholder_path[FS_MAX_PATH] = {0}; + this->MakePath(placeholder_path, placeholder_id); + + FILE* f = nullptr; + R_TRY(OpenFile(&f, placeholder_path, FS_OPEN_WRITE)); + + *out_handle = f; + return ResultSuccess; + } + + bool PlaceHolderAccessor::LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id) { + std::scoped_lock lk(this->cache_mutex); + CacheEntry *entry = this->FindInCache(placeholder_id); + if (!entry) { + return false; + } + *out_handle = entry->handle; + entry->id = InvalidUuid; + entry->handle = nullptr; + return true; + } + + PlaceHolderAccessor::CacheEntry *PlaceHolderAccessor::FindInCache(PlaceHolderId placeholder_id) { + for (size_t i = 0; i < MaxCaches; i++) { + if (placeholder_id == this->caches[i].id) { + return &this->caches[i]; + } + } + return nullptr; + } + + PlaceHolderAccessor::CacheEntry *PlaceHolderAccessor::GetFreeEntry() { + /* Try to find an already free entry. */ + CacheEntry* entry = this->FindInCache(InvalidUuid); + + if (entry) { + return entry; + } + + /* Get the oldest entry. */ + { + entry = &this->caches[0]; + for (size_t i = 1; i < MaxCaches; i++) { + if (entry->counter > this->caches[i].counter) { + entry = &this->caches[i]; + } + } + this->Invalidate(entry); + return entry; + } + } + + void PlaceHolderAccessor::StoreToCache(FILE* handle, PlaceHolderId placeholder_id) { + std::scoped_lock lk(this->cache_mutex); + CacheEntry *entry = this->GetFreeEntry(); + entry->id = placeholder_id; + entry->handle = handle; + entry->counter = this->cur_counter++; + } + + void PlaceHolderAccessor::Invalidate(CacheEntry *entry) { + if (entry != nullptr) { + if (entry->handle != nullptr) { + fflush(entry->handle); + fclose(entry->handle); + entry->handle = nullptr; + } + entry->id = InvalidUuid; + } + } + + void PlaceHolderAccessor::Initialize(char* root, MakePlaceHolderPathFunc path_func, bool delay_flush) { + this->root_path = root; + this->make_placeholder_path_func = path_func; + this->delay_flush = delay_flush; + } + unsigned int PlaceHolderAccessor::GetDirectoryDepth() { if (this->make_placeholder_path_func == static_cast(path::MakePlaceHolderPathFlat)) { return 1; @@ -34,37 +115,18 @@ namespace sts::ncm::impl { std::abort(); } - void PlaceHolderAccessor::GetPlaceHolderPathUncached(char* placeholder_path_out, PlaceHolderId placeholder_id) { - std::scoped_lock lock(this->cache_mutex); - - if (placeholder_id != InvalidUuid) { - CacheEntry* found_cache = NULL; - - for (size_t i = 0; i < PlaceHolderAccessor::MaxCaches; i++) { - CacheEntry* cache = &this->caches[i]; - - if (placeholder_id == cache->id) { - found_cache = cache; - break; - } - } - - if (found_cache) { - /* Flush and close */ - fflush(found_cache->handle); - fclose(found_cache->handle); - std::fill(found_cache->id.uuid, found_cache->id.uuid + sizeof(PlaceHolderId), 0); - } - } - - this->GetPlaceHolderPath(placeholder_path_out, placeholder_id); + void PlaceHolderAccessor::GetPath(char* placeholder_path_out, PlaceHolderId placeholder_id) { + std::scoped_lock lock(this->cache_mutex); + CacheEntry* entry = this->FindInCache(placeholder_id); + this->Invalidate(entry); + this->MakePath(placeholder_path_out, placeholder_id); } Result PlaceHolderAccessor::Create(PlaceHolderId placeholder_id, size_t size) { char placeholder_path[FS_MAX_PATH] = {0}; this->EnsureRecursively(placeholder_id); - this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->GetPath(placeholder_path, placeholder_id); debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { @@ -79,7 +141,7 @@ namespace sts::ncm::impl { Result PlaceHolderAccessor::Delete(PlaceHolderId placeholder_id) { char placeholder_path[FS_MAX_PATH] = {0}; - this->GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->GetPath(placeholder_path, placeholder_id); debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { @@ -93,24 +155,26 @@ namespace sts::ncm::impl { return ResultSuccess; } - Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { - if (this->LoadFromCache(out_handle, placeholder_id)) { - return ResultSuccess; - } - char placeholder_path[FS_MAX_PATH] = {0}; - - this->GetPlaceHolderPath(placeholder_path, placeholder_id); - + Result PlaceHolderAccessor::Write(PlaceHolderId placeholder_id, size_t offset, const void* buffer, size_t size) { FILE* f = nullptr; - R_TRY(OpenFile(&f, placeholder_path, FS_OPEN_WRITE)); - *out_handle = f; + R_TRY_CATCH(this->Open(&f, placeholder_id)) { + R_CATCH(ResultFsPathNotFound) { + return ResultNcmPlaceHolderNotFound; + } + } R_END_TRY_CATCH; + + ON_SCOPE_EXIT { + this->StoreToCache(f, placeholder_id); + }; + + R_TRY(WriteFile(f, offset, buffer, size, !this->delay_flush)); return ResultSuccess; } Result PlaceHolderAccessor::SetSize(PlaceHolderId placeholder_id, size_t size) { char placeholder_path[FS_MAX_PATH] = {0}; - this->GetPlaceHolderPath(placeholder_path, placeholder_id); + this->MakePath(placeholder_path, placeholder_id); if (truncate(placeholder_path, size) == -1) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { @@ -127,7 +191,7 @@ namespace sts::ncm::impl { /* Set the scope for the scoped_lock. */ { - std::scoped_lock lock(this->cache_mutex); + std::scoped_lock lock(this->cache_mutex); if (placeholder_id == InvalidUuid) { *found_in_cache = false; @@ -162,73 +226,15 @@ namespace sts::ncm::impl { Result PlaceHolderAccessor::EnsureRecursively(PlaceHolderId placeholder_id) { char placeholder_path[FS_MAX_PATH] = {0}; - this->GetPlaceHolderPath(placeholder_path, placeholder_id); + this->MakePath(placeholder_path, placeholder_id); R_TRY(EnsureParentDirectoryRecursively(placeholder_path)); return ResultSuccess; } - bool PlaceHolderAccessor::LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id) { - std::scoped_lock lk(this->cache_mutex); - CacheEntry *entry = this->FindInCache(placeholder_id); - if (entry == nullptr) { - return false; - } - entry->id = InvalidUuid; - *out_handle = entry->handle; - return true; - } - - PlaceHolderAccessor::CacheEntry *PlaceHolderAccessor::FindInCache(PlaceHolderId placeholder_id) { - if (placeholder_id == InvalidUuid) { - return nullptr; - } - for (size_t i = 0; i < MaxCaches; i++) { - if (placeholder_id == this->caches[i].id) { - return &this->caches[i]; - } - } - return nullptr; - } - - void PlaceHolderAccessor::StoreToCache(FILE* handle, PlaceHolderId placeholder_id) { - std::scoped_lock lk(this->cache_mutex); - CacheEntry* cache = nullptr; - - /* Find an empty cache */ - for (size_t i = 0; i < MaxCaches; i++) { - if (placeholder_id == InvalidUuid) { - cache = &this->caches[i]; - break; - } - } - - /* No empty caches found. Let's clear cache 0. */ - if (cache == nullptr) { - cache = &this->caches[0]; - - /* Flush and close any handles. */ - if (cache->handle) { - fflush(cache->handle); - fclose(cache->handle); - } - cache->id = InvalidUuid; - } - - /* Cache the new placeholder id and its file handle. */ - cache->id = placeholder_id; - cache->handle = handle; - cache->counter = this->cur_counter; - this->cur_counter++; - } - - void PlaceHolderAccessor::ClearAllCaches() { - for (size_t i = 0; i < MaxCaches; i++) { - CacheEntry* cache = &this->caches[i]; - - if (cache->id != InvalidUuid) { - fflush(cache->handle); - fclose(cache->handle); - cache->id = InvalidUuid; + void PlaceHolderAccessor::InvalidateAll() { + for (auto &entry : this->caches) { + if (entry.id != InvalidUuid) { + this->Invalidate(&entry); } } } diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index 07ece0506..acaed14ce 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -24,53 +24,56 @@ namespace sts::ncm::impl { class PlaceHolderAccessor { - public: + private: class CacheEntry { public: PlaceHolderId id; FILE* handle; u64 counter; }; - - public: + private: static constexpr size_t MaxCaches = 0x2; - CacheEntry caches[MaxCaches]; + std::array caches; char* root_path; u64 cur_counter; HosMutex cache_mutex; MakePlaceHolderPathFunc make_placeholder_path_func; bool delay_flush; - + private: + Result Open(FILE** out_handle, PlaceHolderId placeholder_id); + CacheEntry *FindInCache(PlaceHolderId placeholder_id); + bool LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id); + CacheEntry *GetFreeEntry(); + void StoreToCache(FILE* handle, PlaceHolderId placeholder_id); + void Invalidate(CacheEntry *entry); + public: PlaceHolderAccessor() : cur_counter(0), delay_flush(false) { for (size_t i = 0; i < MaxCaches; i++) { caches[i].id = InvalidUuid; } } - inline void GetPlaceHolderRootPath(char* out_placeholder_root) { + inline void MakeRootPath(char* out_placeholder_root) { path::GetPlaceHolderRootPath(out_placeholder_root, this->root_path); } - inline void GetPlaceHolderPath(char* out_placeholder_path, PlaceHolderId placeholder_id) { + inline void MakePath(char* out_placeholder_path, PlaceHolderId placeholder_id) { char placeholder_root_path[FS_MAX_PATH] = {0}; - this->GetPlaceHolderRootPath(placeholder_root_path); + this->MakeRootPath(placeholder_root_path); this->make_placeholder_path_func(out_placeholder_path, placeholder_id, placeholder_root_path); } + void Initialize(char* root, MakePlaceHolderPathFunc path_func, bool delay_flush); unsigned int GetDirectoryDepth(); - void GetPlaceHolderPathUncached(char* out_placeholder_path, PlaceHolderId placeholder_id); + void GetPath(char* out_placeholder_path, PlaceHolderId placeholder_id); Result Create(PlaceHolderId placeholder_id, size_t size); Result Delete(PlaceHolderId placeholder_id); - Result Open(FILE** out_handle, PlaceHolderId placeholder_id); + Result Write(PlaceHolderId placeholder_id, size_t offset, const void* buffer, size_t size); Result SetSize(PlaceHolderId placeholder_id, size_t size); Result GetSize(bool* found_in_cache, size_t* out_size, PlaceHolderId placeholder_id); Result EnsureRecursively(PlaceHolderId placeholder_id); - - CacheEntry *FindInCache(PlaceHolderId placeholder_id); - bool LoadFromCache(FILE** out_handle, PlaceHolderId placeholder_id); - void StoreToCache(FILE* handle, PlaceHolderId placeholder_id); - void ClearAllCaches(); + void InvalidateAll(); }; } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 3a698a9ba..8df832ff2 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -39,15 +39,13 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; - this->placeholder_accessor.root_path = this->root_path; - this->placeholder_accessor.make_placeholder_path_func = *placeholder_path_func; - this->placeholder_accessor.delay_flush = delay_flush; + this->placeholder_accessor.Initialize(this->root_path, *placeholder_path_func, delay_flush); return ResultSuccess; } void ContentStorageInterface::Finalize() { this->ClearContentCache(); - this->placeholder_accessor.ClearAllCaches(); + this->placeholder_accessor.InvalidateAll(); } void ContentStorageInterface::ClearContentCache() { @@ -126,7 +124,7 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderPath(placeholder_path, placeholder_id); + this->placeholder_accessor.MakePath(placeholder_path, placeholder_id); bool has = false; R_TRY(HasFile(&has, placeholder_path)); @@ -144,21 +142,7 @@ namespace sts::ncm { } R_TRY(this->EnsureEnabled()); - - FILE* f = nullptr; - - R_TRY_CATCH(this->placeholder_accessor.Open(&f, placeholder_id)) { - R_CATCH(ResultFsPathNotFound) { - return ResultNcmPlaceHolderNotFound; - } - } R_END_TRY_CATCH; - - ON_SCOPE_EXIT { - this->placeholder_accessor.StoreToCache(f, placeholder_id); - }; - - R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, !this->placeholder_accessor.delay_flush)); - + R_TRY(this->placeholder_accessor.Write(placeholder_id, offset, data.buffer, data.num_elements)); return ResultSuccess; R_DEBUG_END } @@ -171,7 +155,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char content_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); this->GetContentPath(content_path, content_id); if (rename(placeholder_path, content_path) != 0) { @@ -244,7 +228,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; @@ -256,8 +240,8 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.ClearAllCaches(); - this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + this->placeholder_accessor.InvalidateAll(); + this->placeholder_accessor.MakeRootPath(placeholder_root_path); /* Nintendo uses CleanDirectoryRecursively which is 3.0.0+. We'll just delete the directory and recreate it to support all firmwares. */ @@ -276,7 +260,7 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + this->placeholder_accessor.MakeRootPath(placeholder_root_path); const unsigned int dir_depth = this->placeholder_accessor.GetDirectoryDepth(); size_t entry_count = 0; @@ -403,7 +387,7 @@ namespace sts::ncm { R_DEBUG_START this->disabled = true; this->ClearContentCache(); - this->placeholder_accessor.ClearAllCaches(); + this->placeholder_accessor.InvalidateAll(); return ResultSuccess; R_DEBUG_END } @@ -423,7 +407,7 @@ namespace sts::ncm { R_TRY(EnsureParentDirectoryRecursively(new_content_path)); R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); if (rename(old_content_path, placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { @@ -474,7 +458,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); @@ -607,7 +591,7 @@ namespace sts::ncm { Result ContentStorageInterface::FlushPlaceHolder() { R_DEBUG_START - this->placeholder_accessor.ClearAllCaches(); + this->placeholder_accessor.InvalidateAll(); return ResultSuccess; R_DEBUG_END } @@ -629,7 +613,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; struct stat st; - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); if (stat(placeholder_path, &st) == -1) { return fsdevGetLastResult(); } @@ -662,8 +646,8 @@ namespace sts::ncm { R_TRY(TraverseDirectory(content_root_path, dir_depth, fix_file_attributes)); char placeholder_root_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.ClearAllCaches(); - this->placeholder_accessor.GetPlaceHolderRootPath(placeholder_root_path); + this->placeholder_accessor.InvalidateAll(); + this->placeholder_accessor.MakeRootPath(placeholder_root_path); dir_depth = this->placeholder_accessor.GetDirectoryDepth(); R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); @@ -699,7 +683,7 @@ namespace sts::ncm { u8 key_generation = 0; char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; - this->placeholder_accessor.GetPlaceHolderPathUncached(placeholder_path, placeholder_id); + this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); From 168447d80e9640768fb1b43f04a385507c1bb5ab Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 8 Aug 2019 18:24:56 +1000 Subject: [PATCH 33/58] Remove debug code (again) --- stratosphere/ncm/source/debug.cpp | 145 ------------------ stratosphere/ncm/source/debug.hpp | 39 ----- .../ncm/source/impl/ncm_content_manager.cpp | 6 - .../source/impl/ncm_placeholder_accessor.cpp | 4 - .../lr_addoncontentlocationresolver.cpp | 8 - .../ncm/source/lr_contentlocationresolver.cpp | 46 ------ .../ncm/source/lr_manager_service.cpp | 10 -- .../lr_redirectonlylocationresolver.cpp | 42 ----- .../source/lr_registeredlocationresolver.cpp | 20 --- .../source/ncm_content_manager_service.cpp | 30 ---- .../ncm/source/ncm_contentmetadatabase.cpp | 83 ---------- .../ncm/source/ncm_contentstorage.cpp | 64 -------- stratosphere/ncm/source/ncm_fs.cpp | 6 - stratosphere/ncm/source/ncm_main.cpp | 2 - .../ncm/source/ncm_readonlycontentstorage.cpp | 60 -------- 15 files changed, 565 deletions(-) delete mode 100644 stratosphere/ncm/source/debug.cpp delete mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp deleted file mode 100644 index 872802928..000000000 --- a/stratosphere/ncm/source/debug.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include - -#include "impl/ncm_content_manager.hpp" -#include "debug.hpp" -#include "ncm_fs.hpp" - -namespace sts::debug { - - #define IRAM_BASE 0x40000000ull - #define IRAM_SIZE 0x40000 - - #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 - #define IRAM_PAYLOAD_BASE 0x40010000ull - - #define IRAM_SAFE_START 0x40038000ull - #define IRAM_SAFE_END 0x4003D000ull - #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START - - namespace { - - HosMutex g_log_mutex; - - } - - size_t g_curr_log_offset = 0; - size_t g_log_skip = 1000; - u32 g_page_num = 0; - - char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; - - void clear_iram(void) { - /* Fill with null*/ - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Overwrite all of our log's IRAM with 0s. */ - for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { - CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); - } - } - - void clear_log(void) { - std::scoped_lock lk(g_log_mutex); - - clear_iram(); - } - - Result Initialize() { - clear_log(); - return ResultSuccess; - } - - void DebugLog(const char* format, ...) { - std::scoped_lock lk(g_log_mutex); - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Format a string with our arguments. */ - va_list args; - va_start(args, format); - vsnprintf(g_work_page, 0x1000, format, args); - va_end(args); - - size_t msg_len = strnlen(g_work_page, 0x1000); - - /* Nothing to log. */ - if (msg_len == 0) { - return; - } - - /* Attempt to put some of our new string in the previous 4 bytes. */ - if (g_curr_log_offset >= 4) { - char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; - CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); - size_t prev_4_size = strnlen(prev_4, 4); - - /* Do we have room to put some of our new string in the old one? */ - if (prev_4_size < 4) { - size_t spare_4_space = 4 - prev_4_size; - memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); - - /* Copy the previous 4 bytes back. */ - CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); - memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); - /* Update our size again. */ - msg_len = strnlen(g_work_page, 0x1000); - } - } - - size_t msg_len_aligned = (msg_len + 3) & ~3; - - if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { - if (g_log_skip == 0) { - /* Log is full. Reboot to RCM to read it. */ - RebootToRcm(); - return; - } - - g_log_skip--; - g_curr_log_offset = 0; - g_page_num++; - clear_iram(); - CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); - } - - /* Fill remainder with 0s. */ - if (msg_len_aligned > msg_len) { - memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); - } - - uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; - uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); - - /* We are copying across two pages */ - if (iram_out_start + msg_len_aligned > iram_next_page) { - size_t first_page_size = iram_next_page - iram_out_start; - CopyToIram(iram_out_start, g_work_page, first_page_size); - CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); - } else { - CopyToIram(iram_out_start, g_work_page, msg_len_aligned); - } - - g_curr_log_offset += msg_len_aligned; - } - - void LogBytes(const void* buf, size_t len) { - if (buf == NULL || len == 0) { - return; - } - - const u8* bytes = static_cast(buf); - int count = 0; - DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); - DebugLog("-----------------------------------------------\n"); - - for (size_t i = 0; i < len; i++) { - DebugLog("%02x ", bytes[i]); - count++; - if ((count % 16) == 0) { - DebugLog("\n"); - } - } - - DebugLog("\n"); - } -} - diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp deleted file mode 100644 index 0eca28d9a..000000000 --- a/stratosphere/ncm/source/debug.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Adubbz - * - * 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 . - */ - -#pragma once -#include -#include -#include - -namespace sts::debug { - #define STR_(X) #X - #define STR(X) STR_(X) - - #define D_LOG(format, ...) \ - debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); - #define R_DEBUG_START \ - Result rc = [&]() -> Result { - #define R_DEBUG_END \ - }(); \ - D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ - return rc; - - Result Initialize(); - void DebugLog(const char* format, ...); - void LogBytes(const void* buf, size_t len); - -} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 6d3d6af74..7d403fb82 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,7 +19,6 @@ #include #include -#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -150,9 +149,6 @@ namespace sts::ncm::impl { if (g_initialized) { return ResultSuccess; } - - R_ASSERT(debug::Initialize()); - debug::DebugLog("ContentManager::InitializeContentManager\n"); size_t cur_storage_index = g_num_content_storage_entries; @@ -257,8 +253,6 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { - debug::DebugLog("Finalizing content manager...\n"); - { std::scoped_lock lk(g_mutex); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index ba3a8249f..357fb1d7c 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,8 +20,6 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" -#include "../debug.hpp" - namespace sts::ncm::impl { Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { @@ -128,7 +126,6 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPath(placeholder_path, placeholder_id); - debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -143,7 +140,6 @@ namespace sts::ncm::impl { this->GetPath(placeholder_path, placeholder_id); - debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 4d4d5e1ef..a6051bdc9 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -26,7 +24,6 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -45,21 +42,16 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { - R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { - R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 8dd735cef..95680e8bd 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -48,21 +45,15 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -71,11 +62,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -84,39 +73,29 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -125,18 +104,14 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { - R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -151,57 +126,43 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -217,28 +178,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 82b11f7ec..6958cb11e 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -17,33 +17,23 @@ #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" -#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { - R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); - R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { - R_DEBUG_START - D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 0c6ca239d..b140e69b1 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -39,18 +36,14 @@ namespace sts::lr { } return ResultLrProgramNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -59,11 +52,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -72,31 +63,23 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START return ResultLrDataNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -105,75 +88,57 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { - R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -189,28 +154,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 1b5197fe8..a21c41120 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,8 +16,6 @@ #include "lr_registeredlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -32,7 +30,6 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -43,11 +40,9 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -56,26 +51,20 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -86,11 +75,9 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -99,30 +86,23 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { - R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index b7c5acb11..cd95b9191 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,94 +17,64 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ContentManagerService::CreateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 5c0478373..72a46e2e9 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,8 +17,6 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { namespace { @@ -95,11 +93,6 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version) - D_LOG("type: 0x%x\n", type); - D_LOG("id_offset: 0x%x\n", id_offset); - const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -146,9 +139,6 @@ namespace sts::ncm { return ResultNcmContentNotFound; } - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, found_content_info->content_id); - D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -180,50 +170,36 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - - D_LOG(" set title_id: 0x%lx\n", key.id); - D_LOG(" set version: 0x%x\n", key.version); - R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { - R_DEBUG_START if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } R_TRY(this->EnsureEnabled()); - const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -237,22 +213,14 @@ namespace sts::ncm { out_count.SetValue(count); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; - D_LOG("app tid: 0x%x\n", application_title_id); - D_LOG("meta type: 0x%x\n", type); - D_LOG("install type: 0x%x\n", install_type); - D_LOG("tid min: 0x%lx\n", title_id_min); - D_LOG("tid max: 0x%lx\n", title_id_max); - /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -304,21 +272,17 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; @@ -369,11 +333,9 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -387,16 +349,11 @@ namespace sts::ncm { has = it->GetKey() == key; } - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version); - D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); bool has = true; @@ -406,11 +363,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -424,11 +379,9 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { @@ -444,40 +397,30 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } - D_LOG(" key title_id: 0x%lx\n", key.id); - D_LOG(" key version: 0x%x\n", key.version); - const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); out_patch_id.SetValue(ext_header->patch_id); - D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { @@ -522,28 +465,17 @@ namespace sts::ncm { } } - for (size_t i = 0; i < content_ids.num_elements; i++) { - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, content_ids[i]); - D_LOG("content id: %s.nca\n", content_name); - D_LOG("orphaned: %d\n", out_orphaned[i]); - } - return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { - R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -563,11 +495,9 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { - R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -598,11 +528,9 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const void* value = nullptr; @@ -611,11 +539,9 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { @@ -628,16 +554,13 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -657,7 +580,6 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); @@ -677,20 +599,15 @@ namespace sts::ncm { *out_key = *found_key; return ResultSuccess; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 8df832ff2..ca98a89f0 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,8 +20,6 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -89,16 +87,13 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -108,19 +103,14 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - return this->placeholder_accessor.Delete(placeholder_id); - R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -131,11 +121,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -144,11 +132,9 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); R_TRY(this->placeholder_accessor.Write(placeholder_id, offset, data.buffer, data.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START this->ClearContentCache(); R_TRY(this->EnsureEnabled()); @@ -170,11 +156,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); this->ClearContentCache(); @@ -190,11 +174,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -205,11 +187,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -217,13 +197,10 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; - D_LOG("path: %s\n", common_path); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -232,11 +209,9 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -252,11 +227,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -283,11 +256,9 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; @@ -308,11 +279,9 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -358,16 +327,13 @@ namespace sts::ncm { for (size_t i = 0; i < entry_count; i++) { char content_name[sizeof(ContentId)*2+1] = {0}; GetStringFromContentId(content_name, out_buf[i]); - D_LOG("content id: %s.nca\n", content_name); } out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -380,20 +346,16 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.InvalidateAll(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char old_content_path[FS_MAX_PATH] = {0}; @@ -420,20 +382,15 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -446,11 +403,9 @@ namespace sts::ncm { R_TRY(ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -466,11 +421,9 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -527,11 +480,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -560,44 +511,34 @@ namespace sts::ncm { R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START this->placeholder_accessor.InvalidateAll(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); bool found_in_cache = false; @@ -620,11 +561,9 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -653,11 +592,9 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -714,7 +651,6 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 03a1941b8..e3301bb23 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -21,8 +21,6 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode) { @@ -61,9 +59,6 @@ namespace sts::ncm { } Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option) { - R_DEBUG_START - D_LOG("Writing 0x%llx to offset 0x%llx\n", size, offset); - if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -77,7 +72,6 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ReadFile(FILE* f, size_t offset, void* buffer, size_t size) { diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 2904a833c..14ccc2617 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,8 +22,6 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - extern "C" { extern u32 __start__; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index b70b36d7d..de8dd26b8 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,12 +18,9 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -35,53 +32,37 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -97,11 +78,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -119,41 +98,29 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -173,30 +140,22 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -224,17 +183,13 @@ namespace sts::ncm { R_TRY(ReadFile(f, offset, buf.buffer, buf.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -258,51 +213,36 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } } \ No newline at end of file From e7330a52f36852ba0e8c4ec956b7f3b0876aea10 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 8 Aug 2019 20:12:21 +1000 Subject: [PATCH 34/58] Revert "Remove debug code (again)" This reverts commit 168447d80e9640768fb1b43f04a385507c1bb5ab. --- stratosphere/ncm/source/debug.cpp | 145 ++++++++++++++++++ stratosphere/ncm/source/debug.hpp | 39 +++++ .../ncm/source/impl/ncm_content_manager.cpp | 6 + .../source/impl/ncm_placeholder_accessor.cpp | 4 + .../lr_addoncontentlocationresolver.cpp | 8 + .../ncm/source/lr_contentlocationresolver.cpp | 46 ++++++ .../ncm/source/lr_manager_service.cpp | 10 ++ .../lr_redirectonlylocationresolver.cpp | 42 +++++ .../source/lr_registeredlocationresolver.cpp | 20 +++ .../source/ncm_content_manager_service.cpp | 30 ++++ .../ncm/source/ncm_contentmetadatabase.cpp | 83 ++++++++++ .../ncm/source/ncm_contentstorage.cpp | 64 ++++++++ stratosphere/ncm/source/ncm_fs.cpp | 6 + stratosphere/ncm/source/ncm_main.cpp | 2 + .../ncm/source/ncm_readonlycontentstorage.cpp | 60 ++++++++ 15 files changed, 565 insertions(+) create mode 100644 stratosphere/ncm/source/debug.cpp create mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp new file mode 100644 index 000000000..872802928 --- /dev/null +++ b/stratosphere/ncm/source/debug.cpp @@ -0,0 +1,145 @@ +#include + +#include "impl/ncm_content_manager.hpp" +#include "debug.hpp" +#include "ncm_fs.hpp" + +namespace sts::debug { + + #define IRAM_BASE 0x40000000ull + #define IRAM_SIZE 0x40000 + + #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 + #define IRAM_PAYLOAD_BASE 0x40010000ull + + #define IRAM_SAFE_START 0x40038000ull + #define IRAM_SAFE_END 0x4003D000ull + #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START + + namespace { + + HosMutex g_log_mutex; + + } + + size_t g_curr_log_offset = 0; + size_t g_log_skip = 1000; + u32 g_page_num = 0; + + char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; + + void clear_iram(void) { + /* Fill with null*/ + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Overwrite all of our log's IRAM with 0s. */ + for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); + } + } + + void clear_log(void) { + std::scoped_lock lk(g_log_mutex); + + clear_iram(); + } + + Result Initialize() { + clear_log(); + return ResultSuccess; + } + + void DebugLog(const char* format, ...) { + std::scoped_lock lk(g_log_mutex); + memset(g_work_page, 0, sizeof(g_work_page)); + + /* Format a string with our arguments. */ + va_list args; + va_start(args, format); + vsnprintf(g_work_page, 0x1000, format, args); + va_end(args); + + size_t msg_len = strnlen(g_work_page, 0x1000); + + /* Nothing to log. */ + if (msg_len == 0) { + return; + } + + /* Attempt to put some of our new string in the previous 4 bytes. */ + if (g_curr_log_offset >= 4) { + char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; + CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); + size_t prev_4_size = strnlen(prev_4, 4); + + /* Do we have room to put some of our new string in the old one? */ + if (prev_4_size < 4) { + size_t spare_4_space = 4 - prev_4_size; + memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); + + /* Copy the previous 4 bytes back. */ + CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); + memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); + /* Update our size again. */ + msg_len = strnlen(g_work_page, 0x1000); + } + } + + size_t msg_len_aligned = (msg_len + 3) & ~3; + + if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { + if (g_log_skip == 0) { + /* Log is full. Reboot to RCM to read it. */ + RebootToRcm(); + return; + } + + g_log_skip--; + g_curr_log_offset = 0; + g_page_num++; + clear_iram(); + CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); + } + + /* Fill remainder with 0s. */ + if (msg_len_aligned > msg_len) { + memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); + } + + uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; + uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); + + /* We are copying across two pages */ + if (iram_out_start + msg_len_aligned > iram_next_page) { + size_t first_page_size = iram_next_page - iram_out_start; + CopyToIram(iram_out_start, g_work_page, first_page_size); + CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); + } else { + CopyToIram(iram_out_start, g_work_page, msg_len_aligned); + } + + g_curr_log_offset += msg_len_aligned; + } + + void LogBytes(const void* buf, size_t len) { + if (buf == NULL || len == 0) { + return; + } + + const u8* bytes = static_cast(buf); + int count = 0; + DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); + DebugLog("-----------------------------------------------\n"); + + for (size_t i = 0; i < len; i++) { + DebugLog("%02x ", bytes[i]); + count++; + if ((count % 16) == 0) { + DebugLog("\n"); + } + } + + DebugLog("\n"); + } +} + diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp new file mode 100644 index 000000000..0eca28d9a --- /dev/null +++ b/stratosphere/ncm/source/debug.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include +#include + +namespace sts::debug { + #define STR_(X) #X + #define STR(X) STR_(X) + + #define D_LOG(format, ...) \ + debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); + #define R_DEBUG_START \ + Result rc = [&]() -> Result { + #define R_DEBUG_END \ + }(); \ + D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ + return rc; + + Result Initialize(); + void DebugLog(const char* format, ...); + void LogBytes(const void* buf, size_t len); + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 7d403fb82..6d3d6af74 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,6 +19,7 @@ #include #include +#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -149,6 +150,9 @@ namespace sts::ncm::impl { if (g_initialized) { return ResultSuccess; } + + R_ASSERT(debug::Initialize()); + debug::DebugLog("ContentManager::InitializeContentManager\n"); size_t cur_storage_index = g_num_content_storage_entries; @@ -253,6 +257,8 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { + debug::DebugLog("Finalizing content manager...\n"); + { std::scoped_lock lk(g_mutex); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 357fb1d7c..ba3a8249f 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,6 +20,8 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" +#include "../debug.hpp" + namespace sts::ncm::impl { Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { @@ -126,6 +128,7 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPath(placeholder_path, placeholder_id); + debug::DebugLog("Creating %s\n", placeholder_path); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -140,6 +143,7 @@ namespace sts::ncm::impl { this->GetPath(placeholder_path, placeholder_id); + debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index a6051bdc9..4d4d5e1ef 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -24,6 +26,7 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -42,16 +45,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { + R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; + R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { + R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 95680e8bd..8dd735cef 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -45,15 +48,21 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; + D_LOG("path: %s\n", path.path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -62,9 +71,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -73,29 +84,39 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; + D_LOG("path: %s\n", path.path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); + D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -104,14 +125,18 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { + R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -126,43 +151,57 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -178,21 +217,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 6958cb11e..82b11f7ec 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -17,23 +17,33 @@ #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" +#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { + R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); + R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { + R_DEBUG_START + D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); + R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { + R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index b140e69b1..0c6ca239d 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,6 +17,8 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -28,6 +30,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -36,14 +39,18 @@ namespace sts::lr { } return ResultLrProgramNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -52,9 +59,11 @@ namespace sts::lr { } return ResultLrControlNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -63,23 +72,31 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START return ResultLrDataNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -88,57 +105,75 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { + R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { + R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { + R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { + R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { + R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { + R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -154,21 +189,28 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; + R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { + R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index a21c41120..1b5197fe8 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,6 +16,8 @@ #include "lr_registeredlocationresolver.hpp" +#include "debug.hpp" + namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -30,6 +32,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -40,9 +43,11 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -51,20 +56,26 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { + R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -75,9 +86,11 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -86,23 +99,30 @@ namespace sts::lr { } return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { + R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; + R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { + R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index cd95b9191..b7c5acb11 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,64 +17,94 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + namespace sts::ncm { Result ContentManagerService::CreateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { + R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { + R_DEBUG_START + D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; + R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { + R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); + R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentStorage(storage_id); + R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); + R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { + R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 72a46e2e9..5c0478373 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,6 +17,8 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { namespace { @@ -93,6 +95,11 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version) + D_LOG("type: 0x%x\n", type); + D_LOG("id_offset: 0x%x\n", id_offset); + const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -139,6 +146,9 @@ namespace sts::ncm { return ResultNcmContentNotFound; } + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, found_content_info->content_id); + D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -170,36 +180,50 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); + + D_LOG(" set title_id: 0x%lx\n", key.id); + D_LOG(" set version: 0x%x\n", key.version); + R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { + R_DEBUG_START if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } R_TRY(this->EnsureEnabled()); + const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -213,14 +237,22 @@ namespace sts::ncm { out_count.SetValue(count); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; + D_LOG("app tid: 0x%x\n", application_title_id); + D_LOG("meta type: 0x%x\n", type); + D_LOG("install type: 0x%x\n", install_type); + D_LOG("tid min: 0x%lx\n", title_id_min); + D_LOG("tid max: 0x%lx\n", title_id_max); + /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -272,17 +304,21 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; @@ -333,9 +369,11 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -349,11 +387,16 @@ namespace sts::ncm { has = it->GetKey() == key; } + D_LOG("key id: 0x%lx\n", key.id); + D_LOG("key version: 0x%x\n", key.version); + D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); bool has = true; @@ -363,9 +406,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -379,9 +424,11 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { @@ -397,30 +444,40 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } + D_LOG(" key title_id: 0x%lx\n", key.id); + D_LOG(" key version: 0x%x\n", key.version); + const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); out_patch_id.SetValue(ext_header->patch_id); + D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { @@ -465,17 +522,28 @@ namespace sts::ncm { } } + for (size_t i = 0; i < content_ids.num_elements; i++) { + char content_name[sizeof(ContentId)*2+1] = {0}; + GetStringFromContentId(content_name, content_ids[i]); + D_LOG("content id: %s.nca\n", content_name); + D_LOG("orphaned: %d\n", out_orphaned[i]); + } + return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { + R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -495,9 +563,11 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { + R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -528,9 +598,11 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); const void* value = nullptr; @@ -539,9 +611,11 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { @@ -554,13 +628,16 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { + R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; + R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -580,6 +657,7 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); @@ -599,15 +677,20 @@ namespace sts::ncm { *out_key = *found_key; return ResultSuccess; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { + R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; + R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index ca98a89f0..8df832ff2 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,6 +20,8 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -87,13 +89,16 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -103,14 +108,19 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); + return this->placeholder_accessor.Delete(placeholder_id); + R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -121,9 +131,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -132,9 +144,11 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); R_TRY(this->placeholder_accessor.Write(placeholder_id, offset, data.buffer, data.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START this->ClearContentCache(); R_TRY(this->EnsureEnabled()); @@ -156,9 +170,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); this->ClearContentCache(); @@ -174,9 +190,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -187,9 +205,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -197,10 +217,13 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; + D_LOG("path: %s\n", common_path); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -209,9 +232,11 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -227,9 +252,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -256,9 +283,11 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; @@ -279,9 +308,11 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -327,13 +358,16 @@ namespace sts::ncm { for (size_t i = 0; i < entry_count; i++) { char content_name[sizeof(ContentId)*2+1] = {0}; GetStringFromContentId(content_name, out_buf[i]); + D_LOG("content id: %s.nca\n", content_name); } out_count.SetValue(static_cast(entry_count)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -346,16 +380,20 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.InvalidateAll(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char old_content_path[FS_MAX_PATH] = {0}; @@ -382,15 +420,20 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); + R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -403,9 +446,11 @@ namespace sts::ncm { R_TRY(ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -421,9 +466,11 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -480,9 +527,11 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -511,34 +560,44 @@ namespace sts::ncm { R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } + D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } + D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START this->placeholder_accessor.InvalidateAll(); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); bool found_in_cache = false; @@ -561,9 +620,11 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -592,9 +653,11 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; + R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -651,6 +714,7 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index e3301bb23..03a1941b8 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -21,6 +21,8 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" +#include "debug.hpp" + namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode) { @@ -59,6 +61,9 @@ namespace sts::ncm { } Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option) { + R_DEBUG_START + D_LOG("Writing 0x%llx to offset 0x%llx\n", size, offset); + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } @@ -72,6 +77,7 @@ namespace sts::ncm { } return ResultSuccess; + R_DEBUG_END } Result ReadFile(FILE* f, size_t offset, void* buffer, size_t size) { diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 14ccc2617..2904a833c 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,6 +22,8 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" +#include "debug.hpp" + extern "C" { extern u32 __start__; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index de8dd26b8..b70b36d7d 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,9 +18,12 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" +#include "debug.hpp" + namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -32,37 +35,53 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -78,9 +97,11 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -98,29 +119,41 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -140,22 +173,30 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { + R_DEBUG_START this->disabled = true; return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { + R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -183,13 +224,17 @@ namespace sts::ncm { R_TRY(ReadFile(f, offset, buf.buffer, buf.num_elements)); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { + R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -213,36 +258,51 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { + R_DEBUG_START out_size.SetValue(0); return ResultSuccess; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { + R_DEBUG_START return ResultNcmInvalidContentStorageOperation; + R_DEBUG_END } } \ No newline at end of file From 2df69341943cbf11a89cb67cc201541d87c8dfe4 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 11:28:41 +1000 Subject: [PATCH 35/58] Misc changes --- .../source/impl/ncm_placeholder_accessor.cpp | 1 + .../ncm/source/ncm_contentstorage.cpp | 3 ++ stratosphere/ncm/source/ncm_fs.cpp | 31 ++++++++++++------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index ba3a8249f..79f562e15 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -129,6 +129,7 @@ namespace sts::ncm::impl { this->GetPath(placeholder_path, placeholder_id); debug::DebugLog("Creating %s\n", placeholder_path); + D_LOG("size: 0x%lx\n", size); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 8df832ff2..c33e78835 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -93,6 +93,9 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); + char placeholder_str[FS_MAX_PATH] = {0}; + GetStringFromPlaceHolderId(placeholder_str, *out.GetPointer()); + D_LOG("%s\n", placeholder_str); return ResultSuccess; R_DEBUG_END } diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 03a1941b8..ea5537d6e 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -26,8 +26,10 @@ namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode) { + R_DEBUG_START bool has = false; + D_LOG("path %s\n", path); /* Manually check if the file already exists, so it doesn't get created automatically. */ R_TRY(HasFile(&has, path)); if (!has) { @@ -36,18 +38,12 @@ namespace sts::ncm { const char* fopen_mode = ""; - if (mode & FS_OPEN_APPEND) { - if (mode & FS_OPEN_READ) { - fopen_mode = "r+b"; - } else if (mode & FS_OPEN_WRITE) { - fopen_mode = "w+b"; - } - } else { - if (mode & FS_OPEN_READ) { - fopen_mode = "rb"; - } else if (mode & FS_OPEN_WRITE) { - fopen_mode = "wb"; - } + /* Append is forced regardless of whether we set + as the mode. + We do so so the file doesn't get deleted. */ + if (mode & FS_OPEN_READ) { + fopen_mode = "r+b"; + } else if (mode & FS_OPEN_WRITE) { + fopen_mode = "w+b"; } FILE* f = fopen(path, fopen_mode); @@ -58,12 +54,23 @@ namespace sts::ncm { *out = f; return ResultSuccess; + R_DEBUG_END } Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option) { R_DEBUG_START D_LOG("Writing 0x%llx to offset 0x%llx\n", size, offset); + if (fseek(f, 0, SEEK_END) != 0) { + return fsdevGetLastResult(); + } + size_t existing_size = ftell(f); + + if (offset + size > existing_size) { + D_LOG("offset: 0x%lx, size: 0x%lx, existing_size: 0x%lx\n", offset, size, existing_size); + return ResultFsFileExtensionWithoutOpenModeAllowAppend; + } + if (fseek(f, offset, SEEK_SET) != 0) { return fsdevGetLastResult(); } From c1734f062b0a22ba91af4f9518ca7712a8bff3f6 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 11:36:49 +1000 Subject: [PATCH 36/58] Fixed file modes --- stratosphere/ncm/source/ncm_fs.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index ea5537d6e..7c8f2b7a1 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -38,14 +38,11 @@ namespace sts::ncm { const char* fopen_mode = ""; - /* Append is forced regardless of whether we set + as the mode. - We do so so the file doesn't get deleted. */ - if (mode & FS_OPEN_READ) { + if (mode & FS_OPEN_WRITE) { fopen_mode = "r+b"; - } else if (mode & FS_OPEN_WRITE) { - fopen_mode = "w+b"; - } - + } else if (mode & FS_OPEN_READ) { + fopen_mode = "rb"; + } FILE* f = fopen(path, fopen_mode); if (f == nullptr) { From 15e8e324095859400392bcca8c0baa2a683b7b1f Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 15:30:25 +1000 Subject: [PATCH 37/58] Fixed ContentId/PlaceHolderId alignment --- .../source/impl/ncm_placeholder_accessor.cpp | 12 ++--- .../source/impl/ncm_placeholder_accessor.hpp | 2 +- .../ncm/source/ncm_contentstorage.cpp | 4 +- stratosphere/ncm/source/ncm_types.hpp | 45 +++++++++++++++++-- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 79f562e15..ee48fe63e 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -45,7 +45,7 @@ namespace sts::ncm::impl { return false; } *out_handle = entry->handle; - entry->id = InvalidUuid; + entry->id = InvalidPlaceHolderId; entry->handle = nullptr; return true; } @@ -61,7 +61,7 @@ namespace sts::ncm::impl { PlaceHolderAccessor::CacheEntry *PlaceHolderAccessor::GetFreeEntry() { /* Try to find an already free entry. */ - CacheEntry* entry = this->FindInCache(InvalidUuid); + CacheEntry* entry = this->FindInCache(InvalidPlaceHolderId); if (entry) { return entry; @@ -95,7 +95,7 @@ namespace sts::ncm::impl { fclose(entry->handle); entry->handle = nullptr; } - entry->id = InvalidUuid; + entry->id = InvalidPlaceHolderId; } } @@ -194,7 +194,7 @@ namespace sts::ncm::impl { { std::scoped_lock lock(this->cache_mutex); - if (placeholder_id == InvalidUuid) { + if (placeholder_id == InvalidPlaceHolderId) { *found_in_cache = false; return ResultSuccess; } @@ -206,7 +206,7 @@ namespace sts::ncm::impl { return ResultSuccess; } - cache_entry->id = InvalidUuid; + cache_entry->id = InvalidPlaceHolderId; f = cache_entry->handle; } @@ -234,7 +234,7 @@ namespace sts::ncm::impl { void PlaceHolderAccessor::InvalidateAll() { for (auto &entry : this->caches) { - if (entry.id != InvalidUuid) { + if (entry.id != InvalidPlaceHolderId) { this->Invalidate(&entry); } } diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index acaed14ce..73debc2da 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -50,7 +50,7 @@ namespace sts::ncm::impl { public: PlaceHolderAccessor() : cur_counter(0), delay_flush(false) { for (size_t i = 0; i < MaxCaches; i++) { - caches[i].id = InvalidUuid; + caches[i].id = InvalidPlaceHolderId; } } diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index c33e78835..55889a79b 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -49,9 +49,9 @@ namespace sts::ncm { } void ContentStorageInterface::ClearContentCache() { - if (this->cached_content_id != InvalidUuid) { + if (this->cached_content_id != InvalidContentId) { fclose(this->content_cache_file_handle); - this->cached_content_id = InvalidUuid; + this->cached_content_id = InvalidContentId; } } diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 17c0b5d00..01a80091b 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -34,14 +34,53 @@ namespace sts::ncm { bool operator!=(const Uuid& other) const { return !(*this == other); } + + u8& operator[](size_t i) { + return uuid[i]; + } }; static_assert(sizeof(Uuid) == 0x10, "Uuid definition!"); - static constexpr Uuid InvalidUuid = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + struct PlaceHolderId { + Uuid uuid; - typedef Uuid ContentId; - typedef Uuid PlaceHolderId; + inline operator Uuid() const { + return this->uuid; + } + + bool operator==(const Uuid& other) const { + return this->uuid == other; + } + + bool operator!=(const Uuid& other) const { + return this->uuid != other; + } + } __attribute__((aligned(8))); + + static_assert(__alignof__(PlaceHolderId) == 8, "PlaceHolderId definition!"); + + struct ContentId { + Uuid uuid; + + inline operator Uuid() const { + return this->uuid; + } + + bool operator==(const Uuid& other) const { + return this->uuid == other; + } + + bool operator!=(const Uuid& other) const { + return this->uuid != other; + } + } __attribute__((aligned(4))); + + static_assert(__alignof__(ContentId) == 4, "ContentId definition!"); + + static constexpr Uuid InvalidUuid = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + static constexpr PlaceHolderId InvalidPlaceHolderId = { InvalidUuid }; + static constexpr ContentId InvalidContentId = { InvalidUuid }; enum class ContentMetaType : u8 { Unknown = 0x0, From 1aa23b62bd43db9edf0575f2a503d93aede1c0d1 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 15:44:47 +1000 Subject: [PATCH 38/58] Improved type safety --- stratosphere/ncm/source/ncm_contentstorage.cpp | 4 ++-- stratosphere/ncm/source/ncm_make_path.cpp | 8 ++++---- stratosphere/ncm/source/ncm_types.hpp | 16 ++++++++++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index 55889a79b..dc1794dac 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -518,7 +518,7 @@ namespace sts::ncm { } /* Update the cache. */ - eviction_candidate->uuid = content_id; + eviction_candidate->uuid = content_id.uuid; eviction_candidate->rights_id = rights_id; eviction_candidate->key_generation = key_generation; eviction_candidate->last_accessed = rights_id_cache->counter; @@ -705,7 +705,7 @@ namespace sts::ncm { } /* Update the cache. */ - eviction_candidate->uuid = cache_content_id; + eviction_candidate->uuid = cache_content_id.uuid; eviction_candidate->rights_id = rights_id; eviction_candidate->key_generation = key_generation; eviction_candidate->last_accessed = rights_id_cache->counter; diff --git a/stratosphere/ncm/source/ncm_make_path.cpp b/stratosphere/ncm/source/ncm_make_path.cpp index a4a3ed89d..d43d89379 100644 --- a/stratosphere/ncm/source/ncm_make_path.cpp +++ b/stratosphere/ncm/source/ncm_make_path.cpp @@ -45,7 +45,7 @@ namespace sts::ncm::path { void MakeContentPathDualLayered(char* path_out, ContentId content_id, const char* root) { char content_name[FS_MAX_PATH] = {0}; - const u16 hash = Get16BitSha256HashPrefix(content_id); + const u16 hash = Get16BitSha256HashPrefix(content_id.uuid); const u32 hash_lower = (hash >> 4) & 0x3f; const u32 hash_upper = (hash >> 10) & 0x3f; @@ -57,7 +57,7 @@ namespace sts::ncm::path { void MakeContentPath10BitLayered(char* path_out, ContentId content_id, const char* root) { char content_name[FS_MAX_PATH] = {0}; - const u32 hash = (Get16BitSha256HashPrefix(content_id) >> 6) & 0x3FF; + const u32 hash = (Get16BitSha256HashPrefix(content_id.uuid) >> 6) & 0x3FF; GetContentFileName(content_name, content_id); if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash, content_name) < 0) { std::abort(); @@ -66,7 +66,7 @@ namespace sts::ncm::path { void MakeContentPathHashByteLayered(char* path_out, ContentId content_id, const char* root) { char content_name[FS_MAX_PATH] = {0}; - const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(content_id)); + const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(content_id.uuid)); GetContentFileName(content_name, content_id); if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash_byte, content_name) < 0) { std::abort(); @@ -83,7 +83,7 @@ namespace sts::ncm::path { void MakePlaceHolderPathHashByteLayered(char* path_out, PlaceHolderId placeholder_id, const char* root) { char placeholder_name[FS_MAX_PATH] = {0}; - const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(placeholder_id)); + const u32 hash_byte = static_cast(Get8BitSha256HashPrefix(placeholder_id.uuid)); GetPlaceHolderFileName(placeholder_name, placeholder_id); if (snprintf(path_out, FS_MAX_PATH-1, "%s/%08X/%s", root, hash_byte, placeholder_name) < 0) { std::abort(); diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 01a80091b..8264c4f06 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -45,8 +45,12 @@ namespace sts::ncm { struct PlaceHolderId { Uuid uuid; - inline operator Uuid() const { - return this->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 Uuid& other) const { @@ -63,8 +67,12 @@ namespace sts::ncm { struct ContentId { Uuid uuid; - inline operator Uuid() const { - return this->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 Uuid& other) const { From 0f39d4baec6d463c72a8e5215e0e228538560198 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 17:01:55 +1000 Subject: [PATCH 39/58] Fixed reinitialization --- .../ncm/source/impl/ncm_content_manager.cpp | 21 +++++++++++++----- stratosphere/ncm/source/ncm_fs.cpp | 22 ++++++++++++++++--- stratosphere/ncm/source/ncm_fs.hpp | 2 +- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 6d3d6af74..7138787ee 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -508,7 +508,9 @@ namespace sts::ncm::impl { Unmount(entry->mount_point); }; - R_TRY(EnsureDirectoryRecursively(entry->mount_point)); + D_LOG("storage id: 0x%x\n", storage_id); + D_LOG("creating %s\n", entry->meta_path); + R_TRY(EnsureDirectoryRecursively(entry->meta_path)); R_TRY(fsdevCommitDevice(entry->mount_point)); return ResultSuccess; @@ -517,6 +519,8 @@ namespace sts::ncm::impl { Result VerifyContentMetaDatabase(StorageId storage_id) { std::scoped_lock lk(g_mutex); + D_LOG("storage id: 0x%x\n", storage_id); + if (storage_id == StorageId::GameCard) { return ResultSuccess; } @@ -538,16 +542,19 @@ namespace sts::ncm::impl { mounted_save_data = true; } + ON_SCOPE_EXIT { + if (mounted_save_data) { + Unmount(entry->mount_point); + } + }; + bool has_meta_path = false; R_TRY(HasDirectory(&has_meta_path, entry->meta_path)); if (!has_meta_path) { + D_LOG("Meta path %s not found\n", entry->meta_path); return ResultNcmInvalidContentMetaDatabase; } - if (mounted_save_data) { - Unmount(entry->mount_point); - } - return ResultSuccess; } @@ -657,8 +664,12 @@ namespace sts::ncm::impl { if (storage_id != StorageId::GameCard) { R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + D_LOG("storage_id 0x%x\n", storage_id); + D_LOG("init\n"); R_TRY(entry->kvs->Initialize(entry->meta_path, entry->max_content_metas)); + D_LOG("load\n"); R_TRY(entry->kvs->Load()); + D_LOG("loaded\n"); auto content_meta_database = std::make_shared(&*entry->kvs, entry->mount_point); entry->content_meta_database = std::move(content_meta_database); diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 7c8f2b7a1..58b6f757b 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -170,10 +170,18 @@ namespace sts::ncm { } Result EnsureDirectoryRecursively(const char* dir_path) { - return EnsureRecursively(dir_path, true); + R_TRY(EnsureRecursively(dir_path)); + if (mkdir(dir_path, S_IRWXU) == -1) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathAlreadyExists) { + /* If the path already exists, that's okay. Anything else is an error. */ + } + } R_END_TRY_CATCH; + } + return ResultSuccess; } - Result EnsureRecursively(const char* path, bool is_dir) { + Result EnsureRecursively(const char* path) { if (!path) { return ResultFsNullptrArgument; } @@ -201,6 +209,14 @@ namespace sts::ncm { working_path_buf[i + 1] = '/'; } } + + if (mkdir(working_path_buf + 1, S_IRWXU) == -1) { + R_TRY_CATCH(fsdevGetLastResult()) { + R_CATCH(ResultFsPathAlreadyExists) { + /* If the path already exists, that's okay. Anything else is an error. */ + } + } R_END_TRY_CATCH; + } } } else { return ResultNcmAllocationFailed; @@ -210,7 +226,7 @@ namespace sts::ncm { } Result EnsureParentDirectoryRecursively(const char* path) { - return EnsureRecursively(path, false); + return EnsureRecursively(path); } Result GetGameCardHandle(FsGameCardHandle* out_handle) { diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index 4e857406d..347c323fb 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -34,7 +34,7 @@ namespace sts::ncm { Result EnsureContentAndPlaceHolderRoot(const char* root_path); Result EnsureDirectoryRecursively(const char* dir_path); - Result EnsureRecursively(const char* path, bool is_dir); + Result EnsureRecursively(const char* path); /* Create all parent directories for a file path */ Result EnsureParentDirectoryRecursively(const char* path); From 4b8d7461e7d81bee8374ba1f158b8ad8b42b4ac0 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 9 Aug 2019 17:31:59 +1000 Subject: [PATCH 40/58] Fixed doubleup on path creation --- stratosphere/ncm/source/ncm_fs.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 58b6f757b..b3635ec42 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -209,14 +209,6 @@ namespace sts::ncm { working_path_buf[i + 1] = '/'; } } - - if (mkdir(working_path_buf + 1, S_IRWXU) == -1) { - R_TRY_CATCH(fsdevGetLastResult()) { - R_CATCH(ResultFsPathAlreadyExists) { - /* If the path already exists, that's okay. Anything else is an error. */ - } - } R_END_TRY_CATCH; - } } } else { return ResultNcmAllocationFailed; From 387bcd0b982f567513cfb5691f47d22c731accbd Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 10 Aug 2019 00:51:03 +1000 Subject: [PATCH 41/58] Remove debug code --- stratosphere/ncm/source/debug.cpp | 145 ------------------ stratosphere/ncm/source/debug.hpp | 39 ----- .../ncm/source/impl/ncm_content_manager.cpp | 15 -- .../source/impl/ncm_placeholder_accessor.cpp | 5 - .../lr_addoncontentlocationresolver.cpp | 8 - .../ncm/source/lr_contentlocationresolver.cpp | 46 ------ .../ncm/source/lr_manager_service.cpp | 10 -- .../lr_redirectonlylocationresolver.cpp | 42 ----- .../source/lr_registeredlocationresolver.cpp | 20 --- .../source/ncm_content_manager_service.cpp | 30 ---- .../ncm/source/ncm_contentmetadatabase.cpp | 83 ---------- .../ncm/source/ncm_contentstorage.cpp | 65 -------- stratosphere/ncm/source/ncm_fs.cpp | 10 -- stratosphere/ncm/source/ncm_main.cpp | 2 - .../ncm/source/ncm_readonlycontentstorage.cpp | 60 -------- 15 files changed, 580 deletions(-) delete mode 100644 stratosphere/ncm/source/debug.cpp delete mode 100644 stratosphere/ncm/source/debug.hpp diff --git a/stratosphere/ncm/source/debug.cpp b/stratosphere/ncm/source/debug.cpp deleted file mode 100644 index 872802928..000000000 --- a/stratosphere/ncm/source/debug.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include - -#include "impl/ncm_content_manager.hpp" -#include "debug.hpp" -#include "ncm_fs.hpp" - -namespace sts::debug { - - #define IRAM_BASE 0x40000000ull - #define IRAM_SIZE 0x40000 - - #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 - #define IRAM_PAYLOAD_BASE 0x40010000ull - - #define IRAM_SAFE_START 0x40038000ull - #define IRAM_SAFE_END 0x4003D000ull - #define IRAM_SAFE_SIZE IRAM_SAFE_END - IRAM_SAFE_START - - namespace { - - HosMutex g_log_mutex; - - } - - size_t g_curr_log_offset = 0; - size_t g_log_skip = 1000; - u32 g_page_num = 0; - - char __attribute__ ((aligned (0x1000))) g_work_page[0x1000]; - - void clear_iram(void) { - /* Fill with null*/ - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Overwrite all of our log's IRAM with 0s. */ - for (size_t ofs = 0; ofs < IRAM_SAFE_SIZE; ofs += sizeof(g_work_page)) { - CopyToIram(IRAM_SAFE_START + ofs, g_work_page, sizeof(g_work_page)); - } - } - - void clear_log(void) { - std::scoped_lock lk(g_log_mutex); - - clear_iram(); - } - - Result Initialize() { - clear_log(); - return ResultSuccess; - } - - void DebugLog(const char* format, ...) { - std::scoped_lock lk(g_log_mutex); - memset(g_work_page, 0, sizeof(g_work_page)); - - /* Format a string with our arguments. */ - va_list args; - va_start(args, format); - vsnprintf(g_work_page, 0x1000, format, args); - va_end(args); - - size_t msg_len = strnlen(g_work_page, 0x1000); - - /* Nothing to log. */ - if (msg_len == 0) { - return; - } - - /* Attempt to put some of our new string in the previous 4 bytes. */ - if (g_curr_log_offset >= 4) { - char __attribute__ ((aligned (0x4))) prev_4[4] = {0}; - CopyFromIram(prev_4, IRAM_SAFE_START+g_curr_log_offset-4, 4); - size_t prev_4_size = strnlen(prev_4, 4); - - /* Do we have room to put some of our new string in the old one? */ - if (prev_4_size < 4) { - size_t spare_4_space = 4 - prev_4_size; - memcpy(prev_4 + prev_4_size, g_work_page, spare_4_space); - - /* Copy the previous 4 bytes back. */ - CopyToIram(IRAM_SAFE_START+g_curr_log_offset-4, prev_4, 4); - memmove(g_work_page, g_work_page + spare_4_space, 0x1000-spare_4_space); - /* Update our size again. */ - msg_len = strnlen(g_work_page, 0x1000); - } - } - - size_t msg_len_aligned = (msg_len + 3) & ~3; - - if (g_curr_log_offset + msg_len_aligned > IRAM_SAFE_SIZE) { - if (g_log_skip == 0) { - /* Log is full. Reboot to RCM to read it. */ - RebootToRcm(); - return; - } - - g_log_skip--; - g_curr_log_offset = 0; - g_page_num++; - clear_iram(); - CopyToIram(IRAM_SAFE_END-sizeof(u32), &g_page_num, sizeof(u32)); - } - - /* Fill remainder with 0s. */ - if (msg_len_aligned > msg_len) { - memset(g_work_page + msg_len, '\0', msg_len_aligned - msg_len); - } - - uintptr_t iram_out_start = IRAM_SAFE_START+g_curr_log_offset; - uintptr_t iram_next_page = (iram_out_start + 0x1000-1) & ~(0x1000-1); - - /* We are copying across two pages */ - if (iram_out_start + msg_len_aligned > iram_next_page) { - size_t first_page_size = iram_next_page - iram_out_start; - CopyToIram(iram_out_start, g_work_page, first_page_size); - CopyToIram(iram_next_page, g_work_page+first_page_size, msg_len_aligned-first_page_size); - } else { - CopyToIram(iram_out_start, g_work_page, msg_len_aligned); - } - - g_curr_log_offset += msg_len_aligned; - } - - void LogBytes(const void* buf, size_t len) { - if (buf == NULL || len == 0) { - return; - } - - const u8* bytes = static_cast(buf); - int count = 0; - DebugLog("\n\n00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); - DebugLog("-----------------------------------------------\n"); - - for (size_t i = 0; i < len; i++) { - DebugLog("%02x ", bytes[i]); - count++; - if ((count % 16) == 0) { - DebugLog("\n"); - } - } - - DebugLog("\n"); - } -} - diff --git a/stratosphere/ncm/source/debug.hpp b/stratosphere/ncm/source/debug.hpp deleted file mode 100644 index 0eca28d9a..000000000 --- a/stratosphere/ncm/source/debug.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Adubbz - * - * 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 . - */ - -#pragma once -#include -#include -#include - -namespace sts::debug { - #define STR_(X) #X - #define STR(X) STR_(X) - - #define D_LOG(format, ...) \ - debug::DebugLog("%s:" STR(__LINE__) " " format, __FUNCTION__, ##__VA_ARGS__); - #define R_DEBUG_START \ - Result rc = [&]() -> Result { - #define R_DEBUG_END \ - }(); \ - D_LOG(" -> 0x%08" PRIX32 "\n", rc); \ - return rc; - - Result Initialize(); - void DebugLog(const char* format, ...); - void LogBytes(const void* buf, size_t len); - -} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 7138787ee..a9af78d63 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -19,7 +19,6 @@ #include #include -#include "../debug.hpp" #include "../ncm_contentmetadatabase.hpp" #include "../ncm_contentstorage.hpp" #include "../ncm_fs.hpp" @@ -150,9 +149,6 @@ namespace sts::ncm::impl { if (g_initialized) { return ResultSuccess; } - - R_ASSERT(debug::Initialize()); - debug::DebugLog("ContentManager::InitializeContentManager\n"); size_t cur_storage_index = g_num_content_storage_entries; @@ -257,8 +253,6 @@ namespace sts::ncm::impl { } void FinalizeContentManager() { - debug::DebugLog("Finalizing content manager...\n"); - { std::scoped_lock lk(g_mutex); @@ -508,8 +502,6 @@ namespace sts::ncm::impl { Unmount(entry->mount_point); }; - D_LOG("storage id: 0x%x\n", storage_id); - D_LOG("creating %s\n", entry->meta_path); R_TRY(EnsureDirectoryRecursively(entry->meta_path)); R_TRY(fsdevCommitDevice(entry->mount_point)); @@ -519,8 +511,6 @@ namespace sts::ncm::impl { Result VerifyContentMetaDatabase(StorageId storage_id) { std::scoped_lock lk(g_mutex); - D_LOG("storage id: 0x%x\n", storage_id); - if (storage_id == StorageId::GameCard) { return ResultSuccess; } @@ -551,7 +541,6 @@ namespace sts::ncm::impl { bool has_meta_path = false; R_TRY(HasDirectory(&has_meta_path, entry->meta_path)); if (!has_meta_path) { - D_LOG("Meta path %s not found\n", entry->meta_path); return ResultNcmInvalidContentMetaDatabase; } @@ -664,12 +653,8 @@ namespace sts::ncm::impl { if (storage_id != StorageId::GameCard) { R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; - D_LOG("storage_id 0x%x\n", storage_id); - D_LOG("init\n"); R_TRY(entry->kvs->Initialize(entry->meta_path, entry->max_content_metas)); - D_LOG("load\n"); R_TRY(entry->kvs->Load()); - D_LOG("loaded\n"); auto content_meta_database = std::make_shared(&*entry->kvs, entry->mount_point); entry->content_meta_database = std::move(content_meta_database); diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index ee48fe63e..3c600434e 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -20,8 +20,6 @@ #include "../ncm_make_path.hpp" #include "../ncm_path_utils.hpp" -#include "../debug.hpp" - namespace sts::ncm::impl { Result PlaceHolderAccessor::Open(FILE** out_handle, PlaceHolderId placeholder_id) { @@ -128,8 +126,6 @@ namespace sts::ncm::impl { this->EnsureRecursively(placeholder_id); this->GetPath(placeholder_path, placeholder_id); - debug::DebugLog("Creating %s\n", placeholder_path); - D_LOG("size: 0x%lx\n", size); R_TRY_CATCH(fsdevCreateFile(placeholder_path, size, FS_CREATE_BIG_FILE)) { R_CATCH(ResultFsPathAlreadyExists) { return ResultNcmPlaceHolderAlreadyExists; @@ -144,7 +140,6 @@ namespace sts::ncm::impl { this->GetPath(placeholder_path, placeholder_id); - debug::DebugLog("Deleting %s\n", placeholder_path); if (std::remove(placeholder_path) != 0) { R_TRY_CATCH(fsdevGetLastResult()) { R_CATCH(ResultFsPathNotFound) { diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 4d4d5e1ef..a6051bdc9 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_addoncontentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { @@ -26,7 +24,6 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::StorageId storage_id = ncm::StorageId::None; @@ -45,21 +42,16 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { - R_DEBUG_START R_TRY(this->redirector.SetRedirection(tid, storage_id)); return ResultSuccess; - R_DEBUG_END } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { - R_DEBUG_START this->redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 8dd735cef..95680e8bd 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_contentlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -48,21 +45,15 @@ namespace sts::lr { R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -71,11 +62,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -84,39 +73,29 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); *out.pointer = path; - D_LOG("path: %s\n", path.path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); - D_LOG("path: %s\n", (*path.pointer).path); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -125,18 +104,14 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::Refresh() { - R_DEBUG_START std::shared_ptr content_meta_database; std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); @@ -151,57 +126,43 @@ namespace sts::lr { this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -217,28 +178,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result ContentLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 82b11f7ec..6958cb11e 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -17,33 +17,23 @@ #include "impl/lr_manager.hpp" #include "lr_manager_service.hpp" -#include "debug.hpp" namespace sts::lr { Result LocationResolverManagerService::OpenLocationResolver(Out> out, ncm::StorageId storage_id) { - R_DEBUG_START return impl::OpenLocationResolver(out, storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenRegisteredLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenRegisteredLocationResolver(out); - R_DEBUG_END } Result LocationResolverManagerService::RefreshLocationResolver(ncm::StorageId storage_id) { - R_DEBUG_START - D_LOG("storage_id: 0x%x\n", static_cast(storage_id)); return impl::RefreshLocationResolver(storage_id); - R_DEBUG_END } Result LocationResolverManagerService::OpenAddOnContentLocationResolver(Out> out) { - R_DEBUG_START return impl::OpenAddOnContentLocationResolver(out); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 0c6ca239d..b140e69b1 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -17,8 +17,6 @@ #include "impl/ncm_content_manager.hpp" #include "lr_redirectonlylocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RedirectOnlyLocationResolverInterface::~RedirectOnlyLocationResolverInterface() { @@ -30,7 +28,6 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->program_redirector.FindRedirection(&path, tid)) { @@ -39,18 +36,14 @@ namespace sts::lr { } return ResultLrProgramNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->app_control_redirector.FindRedirection(&path, tid)) { @@ -59,11 +52,9 @@ namespace sts::lr { } return ResultLrControlNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -72,31 +63,23 @@ namespace sts::lr { } return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START return ResultLrDataNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationControlPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->legal_info_redirector.FindRedirection(&path, tid)) { @@ -105,75 +88,57 @@ namespace sts::lr { } return ResultLrLegalInformationNotFound; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationLegalInformationPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::Refresh() { - R_DEBUG_START this->program_redirector.ClearRedirections(); this->debug_program_redirector.ClearRedirections(); this->app_control_redirector.ClearRedirections(); this->html_docs_redirector.ClearRedirections(); this->legal_info_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ClearApplicationRedirection() { - R_DEBUG_START this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirection(ncm::TitleId tid) { - R_DEBUG_START this->program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationControlRedirection(ncm::TitleId tid) { - R_DEBUG_START this->app_control_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationHtmlDocumentRedirection(ncm::TitleId tid) { - R_DEBUG_START this->html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseApplicationLegalInformationRedirection(ncm::TitleId tid) { - R_DEBUG_START this->legal_info_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (this->debug_program_redirector.FindRedirection(&path, tid)) { @@ -189,28 +154,21 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::RedirectApplicationProgramPathForDebug(InPointer path, ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.SetRedirection(tid, *path.pointer, impl::RedirectionFlags_Application); return ResultSuccess; - R_DEBUG_END } Result RedirectOnlyLocationResolverInterface::EraseProgramRedirectionForDebug(ncm::TitleId tid) { - R_DEBUG_START this->debug_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 1b5197fe8..a21c41120 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -16,8 +16,6 @@ #include "lr_registeredlocationresolver.hpp" -#include "debug.hpp" - namespace sts::lr { RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { @@ -32,7 +30,6 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { @@ -43,11 +40,9 @@ namespace sts::lr { *out.pointer = path; return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { @@ -56,26 +51,20 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_program_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->program_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - R_DEBUG_START Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { @@ -86,11 +75,9 @@ namespace sts::lr { *out.pointer = path; return ResultLrHtmlDocumentNotFound; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { @@ -99,30 +86,23 @@ namespace sts::lr { } return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { - R_DEBUG_START this->registered_html_docs_redirector.EraseRedirection(tid); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - R_DEBUG_START Path tmp_path = *path.pointer; this->html_docs_redirector.SetRedirection(tid, tmp_path); return ResultSuccess; - R_DEBUG_END } Result RegisteredLocationResolverInterface::Refresh() { - R_DEBUG_START this->registered_program_redirector.ClearRedirections(); this->registered_html_docs_redirector.ClearRedirections(); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index b7c5acb11..cd95b9191 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -17,94 +17,64 @@ #include "impl/ncm_content_manager.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ContentManagerService::CreateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::CreateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CreateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::VerifyContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::VerifyContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::OpenContentStorage(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_storage; R_TRY(impl::OpenContentStorage(&content_storage, storage_id)); out.SetValue(std::move(content_storage)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::OpenContentMetaDatabase(Out> out, StorageId storage_id) { - R_DEBUG_START - D_LOG("storage id: 0x%x\n", storage_id); std::shared_ptr content_meta_database; R_TRY(impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); out.SetValue(std::move(content_meta_database)); return ResultSuccess; - R_DEBUG_END } Result ContentManagerService::CloseContentStorageForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentStorageForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CloseContentMetaDatabaseForcibly(StorageId storage_id) { - R_DEBUG_START return impl::CloseContentMetaDatabaseForcibly(storage_id); - R_DEBUG_END } Result ContentManagerService::CleanupContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::CleanupContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentStorage(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentStorage(storage_id); - R_DEBUG_END } Result ContentManagerService::ActivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::ActivateContentMetaDatabase(storage_id); - R_DEBUG_END } Result ContentManagerService::InactivateContentMetaDatabase(StorageId storage_id) { - R_DEBUG_START return impl::InactivateContentMetaDatabase(storage_id); - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 5c0478373..72a46e2e9 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -17,8 +17,6 @@ #include "ncm_contentmetadatabase.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { namespace { @@ -95,11 +93,6 @@ namespace sts::ncm { Result ContentMetaDatabaseInterface::GetContentIdByTypeImpl(ContentId* out, const ContentMetaKey& key, ContentType type, std::optional id_offset) { R_TRY(this->EnsureEnabled()); - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version) - D_LOG("type: 0x%x\n", type); - D_LOG("id_offset: 0x%x\n", id_offset); - const auto it = this->kvs->lower_bound(key); if (it == this->kvs->end() || it->GetKey().id != key.id) { return ResultNcmContentMetaNotFound; @@ -146,9 +139,6 @@ namespace sts::ncm { return ResultNcmContentNotFound; } - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, found_content_info->content_id); - D_LOG("content id: %s.nca\n", content_name); *out = found_content_info->content_id; return ResultSuccess; } @@ -180,50 +170,36 @@ namespace sts::ncm { } Result ContentMetaDatabaseInterface::Set(ContentMetaKey key, InBuffer value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - - D_LOG(" set title_id: 0x%lx\n", key.id); - D_LOG(" set version: 0x%x\n", key.version); - R_TRY(this->kvs->Set(key, value.buffer, value.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Get(Out out_size, ContentMetaKey key, OutBuffer out_value) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Get(out_size.GetPointer(), out_value.buffer, out_value.num_elements, key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Remove(ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Remove(key)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByType(Out out_content_id, ContentMetaKey key, ContentType type) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::nullopt)); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentInfo(Out out_count, OutBuffer out_info, ContentMetaKey key, u32 offset) { - R_DEBUG_START if (offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } R_TRY(this->EnsureEnabled()); - const void *value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -237,22 +213,14 @@ namespace sts::ncm { out_count.SetValue(count); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::List(Out out_entries_total, Out out_entries_written, OutBuffer out_info, ContentMetaType type, TitleId application_title_id, TitleId title_id_min, TitleId title_id_max, ContentInstallType install_type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; size_t entries_written = 0; - D_LOG("app tid: 0x%x\n", application_title_id); - D_LOG("meta type: 0x%x\n", type); - D_LOG("install type: 0x%x\n", install_type); - D_LOG("tid min: 0x%lx\n", title_id_min); - D_LOG("tid max: 0x%lx\n", title_id_max); - /* If there are no entries then we've already successfully listed them all. */ if (this->kvs->GetCount() == 0) { out_entries_total.SetValue(entries_total); @@ -304,21 +272,17 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); ContentMetaKey key; R_TRY(this->GetLatestContentMetaKeyImpl(&key, title_id)); out_key.SetValue(key); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListApplication(Out out_entries_total, Out out_entries_written, OutBuffer out_keys, ContentMetaType type) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); size_t entries_total = 0; @@ -369,11 +333,9 @@ namespace sts::ncm { out_entries_total.SetValue(entries_total); out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Has(Out out, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -387,16 +349,11 @@ namespace sts::ncm { has = it->GetKey() == key; } - D_LOG("key id: 0x%lx\n", key.id); - D_LOG("key version: 0x%x\n", key.version); - D_LOG("has: %d\n", has); out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasAll(Out out, InBuffer keys) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); bool has = true; @@ -406,11 +363,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetSize(Out out_size, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (this->kvs->GetCount() == 0) { @@ -424,11 +379,9 @@ namespace sts::ncm { out_size.SetValue(it->GetValueSize()); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredSystemVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application && key.type != ContentMetaType::Patch) { @@ -444,40 +397,30 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_system_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetPatchId(Out out_patch_id, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::Application) { return ResultNcmInvalidContentMetaKey; } - D_LOG(" key title_id: 0x%lx\n", key.id); - D_LOG(" key version: 0x%x\n", key.version); - const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); const auto ext_header = GetValueExtendedHeader(value); out_patch_id.SetValue(ext_header->patch_id); - D_LOG(" patch title_id: 0x%lx\n", *out_patch_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (out_orphaned.num_elements < content_ids.num_elements) { @@ -522,28 +465,17 @@ namespace sts::ncm { } } - for (size_t i = 0; i < content_ids.num_elements; i++) { - char content_name[sizeof(ContentId)*2+1] = {0}; - GetStringFromContentId(content_name, content_ids[i]); - D_LOG("content id: %s.nca\n", content_name); - D_LOG("orphaned: %d\n", out_orphaned[i]); - } - return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); R_TRY(this->kvs->Save()); R_TRY(fsdevCommitDevice(this->mount_name)); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::HasContent(Out out, ContentMetaKey key, ContentId content_id) { - R_DEBUG_START const void* value = nullptr; size_t value_size = 0; R_TRY(GetContentMetaValuePointer(&value, &value_size, key, this->kvs)); @@ -563,11 +495,9 @@ namespace sts::ncm { out.SetValue(false); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::ListContentMetaInfo(Out out_entries_written, OutBuffer out_meta_info, ContentMetaKey key, u32 start_index) { - R_DEBUG_START if (start_index >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -598,11 +528,9 @@ namespace sts::ncm { out_entries_written.SetValue(entries_written); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetAttributes(Out out_attributes, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const void* value = nullptr; @@ -611,11 +539,9 @@ namespace sts::ncm { const auto header = GetValueHeader(value); out_attributes.SetValue(header->attributes); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetRequiredApplicationVersion(Out out_version, ContentMetaKey key) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); if (key.type != ContentMetaType::AddOnContent) { @@ -628,16 +554,13 @@ namespace sts::ncm { const auto ext_header = GetValueExtendedHeader(value); out_version.SetValue(ext_header->required_application_version); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetContentIdByTypeAndIdOffset(Out out_content_id, ContentMetaKey key, ContentType type, u8 id_offset) { - R_DEBUG_START ContentId content_id; R_TRY(this->GetContentIdByTypeImpl(&content_id, key, type, std::optional(id_offset))); out_content_id.SetValue(content_id); return ResultSuccess; - R_DEBUG_END } Result ContentMetaDatabaseInterface::GetLatestProgram(ContentId* out_content_id, TitleId title_id) { @@ -657,7 +580,6 @@ namespace sts::ncm { } Result OnMemoryContentMetaDatabaseInterface::GetLatestContentMetaKey(Out out_key, TitleId title_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const ContentMetaKey key = ContentMetaKey::Make(title_id, 0, ContentMetaType::Unknown); @@ -677,20 +599,15 @@ namespace sts::ncm { *out_key = *found_key; return ResultSuccess; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::LookupOrphanContent(OutBuffer out_orphaned, InBuffer content_ids) { - R_DEBUG_START return ResultNcmInvalidContentMetaDatabase; - R_DEBUG_END } Result OnMemoryContentMetaDatabaseInterface::Commit() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index dc1794dac..b788659f5 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -20,8 +20,6 @@ #include "ncm_make_path.hpp" #include "ncm_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { ContentStorageInterface::~ContentStorageInterface() { @@ -89,19 +87,15 @@ namespace sts::ncm { } Result ContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); sts::rnd::GenerateRandomBytes(out.GetPointer(), sizeof(NcmNcaId)); char placeholder_str[FS_MAX_PATH] = {0}; GetStringFromPlaceHolderId(placeholder_str, *out.GetPointer()); - D_LOG("%s\n", placeholder_str); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -111,19 +105,14 @@ namespace sts::ncm { R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - return this->placeholder_accessor.Delete(placeholder_id); - R_DEBUG_END } Result ContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -134,11 +123,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -147,11 +134,9 @@ namespace sts::ncm { R_TRY(this->EnsureEnabled()); R_TRY(this->placeholder_accessor.Write(placeholder_id, offset, data.buffer, data.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START this->ClearContentCache(); R_TRY(this->EnsureEnabled()); @@ -173,11 +158,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); this->ClearContentCache(); @@ -193,11 +176,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -208,11 +189,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -220,13 +199,10 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; - D_LOG("path: %s\n", common_path); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_path[FS_MAX_PATH] = {0}; @@ -235,11 +211,9 @@ namespace sts::ncm { R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -255,11 +229,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char placeholder_root_path[FS_MAX_PATH] = {0}; @@ -286,11 +258,9 @@ namespace sts::ncm { out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_root_path[FS_MAX_PATH] = {0}; @@ -311,11 +281,9 @@ namespace sts::ncm { out_count.SetValue(content_count); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START if (start_offset >> 0x1f != 0) { return ResultNcmInvalidOffset; } @@ -361,16 +329,13 @@ namespace sts::ncm { for (size_t i = 0; i < entry_count; i++) { char content_name[sizeof(ContentId)*2+1] = {0}; GetStringFromContentId(content_name, out_buf[i]); - D_LOG("content id: %s.nca\n", content_name); } out_count.SetValue(static_cast(entry_count)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -383,20 +348,16 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; this->ClearContentCache(); this->placeholder_accessor.InvalidateAll(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char old_content_path[FS_MAX_PATH] = {0}; @@ -423,20 +384,15 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); - R_TRY(this->placeholder_accessor.SetSize(placeholder_id, size)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -449,11 +405,9 @@ namespace sts::ncm { R_TRY(ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -469,11 +423,9 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -530,11 +482,9 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -563,44 +513,34 @@ namespace sts::ncm { R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("free space: 0x%x\n", st.f_bfree); out_size.SetValue(st.f_bfree); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START struct statvfs st = {0}; if (statvfs(this->root_path, &st) == -1) { return fsdevGetLastResult(); } - D_LOG("total space: 0x%x\n", st.f_blocks); out_size.SetValue(st.f_blocks); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START this->placeholder_accessor.InvalidateAll(); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetSizeFromPlaceHolderId(Out out_size, PlaceHolderId placeholder_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); bool found_in_cache = false; @@ -623,11 +563,9 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START char content_root_path[FS_MAX_PATH] = {0}; this->GetContentRootPath(content_root_path); unsigned int dir_depth = this->GetContentDirectoryDepth(); @@ -656,11 +594,9 @@ namespace sts::ncm { R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; - R_DEBUG_END } Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache(); @@ -717,7 +653,6 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index b3635ec42..9eb201e5a 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -21,15 +21,11 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" -#include "debug.hpp" - namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode) { - R_DEBUG_START bool has = false; - D_LOG("path %s\n", path); /* Manually check if the file already exists, so it doesn't get created automatically. */ R_TRY(HasFile(&has, path)); if (!has) { @@ -51,20 +47,15 @@ namespace sts::ncm { *out = f; return ResultSuccess; - R_DEBUG_END } Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option) { - R_DEBUG_START - D_LOG("Writing 0x%llx to offset 0x%llx\n", size, offset); - if (fseek(f, 0, SEEK_END) != 0) { return fsdevGetLastResult(); } size_t existing_size = ftell(f); if (offset + size > existing_size) { - D_LOG("offset: 0x%lx, size: 0x%lx, existing_size: 0x%lx\n", offset, size, existing_size); return ResultFsFileExtensionWithoutOpenModeAllowAppend; } @@ -81,7 +72,6 @@ namespace sts::ncm { } return ResultSuccess; - R_DEBUG_END } Result ReadFile(FILE* f, size_t offset, void* buffer, size_t size) { diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 2904a833c..14ccc2617 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -22,8 +22,6 @@ #include "lr_manager_service.hpp" #include "ncm_content_manager_service.hpp" -#include "debug.hpp" - extern "C" { extern u32 __start__; diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index b70b36d7d..de8dd26b8 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -18,12 +18,9 @@ #include "ncm_path_utils.hpp" #include "ncm_readonlycontentstorage.hpp" -#include "debug.hpp" - namespace sts::ncm { Result ReadOnlyContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); @@ -35,53 +32,37 @@ namespace sts::ncm { strncpy(this->root_path, root_path, FS_MAX_PATH-2); this->make_content_path_func = *content_path_func; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GeneratePlaceHolderId(Out out) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DeletePlaceHolder(PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::HasPlaceHolder(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WritePlaceHolder(PlaceHolderId placeholder_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Register(PlaceHolderId placeholder_id, ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Delete(ContentId content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::Has(Out out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -97,11 +78,9 @@ namespace sts::ncm { out.SetValue(has); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPath(OutPointerWithServerSize out, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -119,41 +98,29 @@ namespace sts::ncm { *out.pointer = common_path; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetPlaceHolderPath(OutPointerWithServerSize out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::CleanupAllPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListPlaceHolder(Out out_count, OutBuffer out_buf) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetContentCount(Out out_count) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ListContentId(Out out_count, OutBuffer out_buf, u32 start_offset) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromContentId(Out out_size, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); char content_path[FS_MAX_PATH] = {0}; @@ -173,30 +140,22 @@ namespace sts::ncm { out_size.SetValue(st.st_size); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::DisableForcibly() { - R_DEBUG_START this->disabled = true; return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::SetPlaceHolderSize(PlaceHolderId placeholder_id, u64 size) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::ReadContentIdFile(OutBuffer buf, ContentId content_id, u64 offset) { - R_DEBUG_START /* Offset is too large */ if (offset >> 0x3f != 0) { return ResultNcmInvalidOffset; @@ -224,17 +183,13 @@ namespace sts::ncm { R_TRY(ReadFile(f, offset, buf.buffer, buf.num_elements)); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderId(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) { - R_DEBUG_START R_TRY(this->EnsureEnabled()); FsRightsId rights_id = {0}; @@ -258,51 +213,36 @@ namespace sts::ncm { out_key_generation.SetValue(static_cast(key_generation)); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::WriteContentForDebug(ContentId content_id, u64 offset, InBuffer data) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetFreeSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetTotalSpaceSize(Out out_size) { - R_DEBUG_START out_size.SetValue(0); return ResultSuccess; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::FlushPlaceHolder() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetSizeFromPlaceHolderId(Out out, PlaceHolderId placeholder_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::RepairInvalidFileAttribute() { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } Result ReadOnlyContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) { - R_DEBUG_START return ResultNcmInvalidContentStorageOperation; - R_DEBUG_END } } \ No newline at end of file From a8677ac1223a9fef2ffe029a4cbeb183066e5f71 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 10 Aug 2019 17:01:24 +1000 Subject: [PATCH 42/58] Fixed 1.0.0 booting --- .../ncm/source/impl/ncm_content_manager.cpp | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index a9af78d63..bce0f1f5a 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -347,21 +347,27 @@ namespace sts::ncm::impl { auto content_storage = entry->content_storage; if (!content_storage) { - switch (storage_id) { - case StorageId::GameCard: - return ResultNcmGameCardContentStorageNotActive; + /* 1.0.0 activates content storages as soon as they are opened. */ + if (GetRuntimeFirmwareVersion() == FirmwareVersion_100) { + R_TRY(ActivateContentStorage(storage_id)); + content_storage = entry->content_storage; + } else { + switch (storage_id) { + case StorageId::GameCard: + return ResultNcmGameCardContentStorageNotActive; - case StorageId::NandSystem: - return ResultNcmNandSystemContentStorageNotActive; + case StorageId::NandSystem: + return ResultNcmNandSystemContentStorageNotActive; - case StorageId::NandUser: - return ResultNcmNandUserContentStorageNotActive; + case StorageId::NandUser: + return ResultNcmNandUserContentStorageNotActive; - case StorageId::SdCard: - return ResultNcmSdCardContentStorageNotActive; + case StorageId::SdCard: + return ResultNcmSdCardContentStorageNotActive; - default: - return ResultNcmUnknownContentStorageNotActive; + default: + return ResultNcmUnknownContentStorageNotActive; + } } } @@ -563,21 +569,27 @@ namespace sts::ncm::impl { std::shared_ptr content_meta_db = entry->content_meta_database; if (!content_meta_db) { - switch (storage_id) { - case StorageId::GameCard: - return ResultNcmGameCardContentMetaDatabaseNotActive; + /* 1.0.0 activates content meta dbs as soon as they are opened. */ + if (GetRuntimeFirmwareVersion() == FirmwareVersion_100) { + R_TRY(ActivateContentMetaDatabase(storage_id)); + content_meta_db = entry->content_meta_database; + } else { + switch (storage_id) { + case StorageId::GameCard: + return ResultNcmGameCardContentMetaDatabaseNotActive; - case StorageId::NandSystem: - return ResultNcmNandSystemContentMetaDatabaseNotActive; + case StorageId::NandSystem: + return ResultNcmNandSystemContentMetaDatabaseNotActive; - case StorageId::NandUser: - return ResultNcmNandUserContentMetaDatabaseNotActive; + case StorageId::NandUser: + return ResultNcmNandUserContentMetaDatabaseNotActive; - case StorageId::SdCard: - return ResultNcmSdCardContentMetaDatabaseNotActive; + case StorageId::SdCard: + return ResultNcmSdCardContentMetaDatabaseNotActive; - default: - return ResultNcmUnknownContentMetaDatabaseNotActive; + default: + return ResultNcmUnknownContentMetaDatabaseNotActive; + } } } From 42b502425cbfc7ee1bcfd4bdce58bd1d3388e320 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 16:38:44 +1000 Subject: [PATCH 43/58] Correct amount of add on content --- stratosphere/ncm/source/impl/lr_redirection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index b6d346286..834dffe54 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -68,7 +68,7 @@ namespace sts::lr::impl { class AddOnContentRedirector { private: - BoundedMap redirections; + BoundedMap redirections; public: bool FindRedirection(ncm::StorageId *out, ncm::TitleId title_id); Result SetRedirection(ncm::TitleId title_id, ncm::StorageId storage_id); From 81a7fdb42fce3a1982508f34e99c0ff681612115 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 22:23:38 +1000 Subject: [PATCH 44/58] Correct main thread stack size --- stratosphere/ncm/ncm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/ncm/ncm.json b/stratosphere/ncm/ncm.json index ad491289f..5a3ac657b 100644 --- a/stratosphere/ncm/ncm.json +++ b/stratosphere/ncm/ncm.json @@ -1,7 +1,7 @@ { "name": "NCM", "title_id": "0x0100000000000002", - "main_thread_stack_size": "0x20000", + "main_thread_stack_size": "0x00004000", "main_thread_priority": 49, "default_cpu_id": 3, "process_category": 1, From d0be5f095eda1a6e1e717ed4239845ea7d563f09 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 22:58:49 +1000 Subject: [PATCH 45/58] lr: Introducing registered data --- .../ncm/source/impl/lr_redirection.cpp | 50 ---------- .../ncm/source/impl/lr_redirection.hpp | 19 ---- .../ncm/source/impl/lr_registered_data.hpp | 99 +++++++++++++++++++ .../lr_addoncontentlocationresolver.cpp | 13 ++- .../lr_addoncontentlocationresolver.hpp | 6 +- .../source/lr_registeredlocationresolver.cpp | 29 +++--- .../source/lr_registeredlocationresolver.hpp | 6 +- 7 files changed, 122 insertions(+), 100 deletions(-) create mode 100644 stratosphere/ncm/source/impl/lr_registered_data.hpp diff --git a/stratosphere/ncm/source/impl/lr_redirection.cpp b/stratosphere/ncm/source/impl/lr_redirection.cpp index 240e0f575..9af961411 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.cpp +++ b/stratosphere/ncm/source/impl/lr_redirection.cpp @@ -75,56 +75,6 @@ namespace sts::lr::impl { } } - bool RegisteredLocationRedirector::FindRedirection(Path *out, ncm::TitleId title_id) { - auto redirection = this->redirections.Find(title_id); - if (redirection) { - *out = *redirection; - return true; - } - - return false; - } - - bool RegisteredLocationRedirector::SetRedirection(ncm::TitleId title_id, const Path& path) { - if (this->redirections.IsFull()) { - return false; - } - - this->redirections[title_id] = path; - return true; - } - - void RegisteredLocationRedirector::EraseRedirection(ncm::TitleId title_id) { - this->redirections.Remove(title_id); - } - - void RegisteredLocationRedirector::ClearRedirections() { - this->redirections.RemoveAll(); - } - - bool AddOnContentRedirector::FindRedirection(ncm::StorageId *out, ncm::TitleId title_id) { - auto redirection = this->redirections.Find(title_id); - - if (redirection) { - *out = *redirection; - return true; - } - - return false; - } - - Result AddOnContentRedirector::SetRedirection(ncm::TitleId title_id, ncm::StorageId storage_id) { - if (this->redirections.IsFull()) { - return ResultLrTooManyRegisteredPaths; - } - - this->redirections[title_id] = storage_id; - return ResultSuccess; - } - - void AddOnContentRedirector::ClearRedirections() { - this->redirections.RemoveAll(); - } } \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index 834dffe54..fccd85c0d 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -56,23 +56,4 @@ namespace sts::lr::impl { void ClearRedirections(u32 flags = RedirectionFlags_None); }; - class RegisteredLocationRedirector { - private: - BoundedMap redirections; - public: - bool FindRedirection(Path *out, ncm::TitleId title_id); - bool SetRedirection(ncm::TitleId title_id, const Path& path); - void EraseRedirection(ncm::TitleId title_id); - void ClearRedirections(); - }; - - class AddOnContentRedirector { - private: - BoundedMap redirections; - public: - bool FindRedirection(ncm::StorageId *out, ncm::TitleId title_id); - Result SetRedirection(ncm::TitleId title_id, ncm::StorageId storage_id); - void ClearRedirections(); - }; - } \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_registered_data.hpp b/stratosphere/ncm/source/impl/lr_registered_data.hpp new file mode 100644 index 000000000..5d54b8e16 --- /dev/null +++ b/stratosphere/ncm/source/impl/lr_registered_data.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +#include "../lr_types.hpp" + +namespace sts::lr::impl { + + template + class RegisteredData { + NON_COPYABLE(RegisteredData); + NON_MOVEABLE(RegisteredData); + private: + struct Entry { + Value value; + Key key; + bool is_valid; + }; + private: + Entry entries[NumEntries]; + public: + RegisteredData() { + this->Clear(); + } + + bool Register(const Key &key, const Value &value) { + /* Try to find an existing value. */ + for (size_t i = 0; i < NumEntries; i++) { + Entry& entry = this->entries[i]; + if (entry.is_valid && entry.key == key) { + entry.value = value; + return true; + } + } + + for (size_t i = 0; i < NumEntries; i++) { + Entry& entry = this->entries[i]; + if (!entry.is_valid) { + entry.key = key; + entry.value = value; + entry.is_valid = true; + return true; + } + } + + return false; + } + + void Unregister(const Key &key) { + for (size_t i = 0; i < NumEntries; i++) { + Entry& entry = this->entries[i]; + if (entry.is_valid && entry.key == key) { + entry.is_valid = false; + } + } + } + + bool Find(Value *out, const Key &key) { + for (size_t i = 0; i < NumEntries; i++) { + Entry& entry = this->entries[i]; + if (entry.is_valid && entry.key == key) { + *out = entry.value; + return true; + } + } + + return false; + } + + void Clear() { + for (size_t i = 0; i < NumEntries; i++) { + this->entries[i].is_valid = false; + } + } + }; + + template + using RegisteredLocations = RegisteredData; + + template + using RegisteredStorages = RegisteredData; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index a6051bdc9..4f346968d 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -19,15 +19,11 @@ namespace sts::lr { - AddOnContentLocationResolverInterface::AddOnContentLocationResolverInterface() { - this->redirector.ClearRedirections(); - } - Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { Path path; ncm::StorageId storage_id = ncm::StorageId::None; - if (!this->redirector.FindRedirection(&storage_id, tid)) { + if (!this->registered_storages.Find(&storage_id, tid)) { return ResultLrAddOnContentNotFound; } @@ -45,12 +41,15 @@ namespace sts::lr { } Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { - R_TRY(this->redirector.SetRedirection(tid, storage_id)); + if (!this->registered_storages.Register(tid, storage_id)) { + return ResultLrTooManyRegisteredPaths; + } + return ResultSuccess; } Result AddOnContentLocationResolverInterface::UnregisterAllAddOnContentPath() { - this->redirector.ClearRedirections(); + this->registered_storages.Clear(); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp index b0d779430..cb9056b6d 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp @@ -18,7 +18,7 @@ #include #include -#include "impl/lr_redirection.hpp" +#include "impl/lr_registered_data.hpp" #include "lr_types.hpp" namespace sts::lr { @@ -31,9 +31,7 @@ namespace sts::lr { UnregisterAllAddOnContentPath = 2, }; private: - impl::AddOnContentRedirector redirector; - public: - AddOnContentLocationResolverInterface(); + impl::RegisteredStorages registered_storages; public: virtual Result ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid); virtual Result RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid); diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index a21c41120..5d7af37ff 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -18,11 +18,6 @@ namespace sts::lr { - RegisteredLocationResolverInterface::RegisteredLocationResolverInterface() { - this->registered_program_redirector.ClearRedirections(); - this->registered_html_docs_redirector.ClearRedirections(); - } - RegisteredLocationResolverInterface::~RegisteredLocationResolverInterface() { /* Ensure entries are deallocated */ this->html_docs_redirector.ClearRedirections(); @@ -33,7 +28,7 @@ namespace sts::lr { Path path; if (!this->program_redirector.FindRedirection(&path, tid)) { - if (!this->registered_program_redirector.FindRedirection(&path, tid)) { + if (!this->registered_program_locations.Find(&path, tid)) { return ResultLrProgramNotFound; } } @@ -45,16 +40,16 @@ namespace sts::lr { Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; - if (!this->registered_program_redirector.SetRedirection(tid, tmp_path)) { - this->registered_program_redirector.ClearRedirections(); - this->registered_program_redirector.SetRedirection(tid, tmp_path); + if (!this->registered_program_locations.Register(tid, tmp_path)) { + this->registered_program_locations.Clear(); + this->registered_program_locations.Register(tid, tmp_path); } return ResultSuccess; } Result RegisteredLocationResolverInterface::UnregisterProgramPath(ncm::TitleId tid) { - this->registered_program_redirector.EraseRedirection(tid); + this->registered_program_locations.Unregister(tid); return ResultSuccess; } @@ -68,7 +63,7 @@ namespace sts::lr { Path path; if (!this->html_docs_redirector.FindRedirection(&path, tid)) { - if (!this->registered_html_docs_redirector.FindRedirection(&path, tid)) { + if (!this->registered_html_docs_locations.Find(&path, tid)) { return ResultLrProgramNotFound; } } @@ -80,16 +75,16 @@ namespace sts::lr { Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { Path tmp_path = *path.pointer; - if (!this->registered_html_docs_redirector.SetRedirection(tid, tmp_path)) { - this->registered_html_docs_redirector.ClearRedirections(); - this->registered_html_docs_redirector.SetRedirection(tid, tmp_path); + if (!this->registered_html_docs_locations.Register(tid, tmp_path)) { + this->registered_html_docs_locations.Clear(); + this->registered_html_docs_locations.Register(tid, tmp_path); } return ResultSuccess; } Result RegisteredLocationResolverInterface::UnregisterHtmlDocumentPath(ncm::TitleId tid) { - this->registered_html_docs_redirector.EraseRedirection(tid); + this->registered_html_docs_locations.Unregister(tid); return ResultSuccess; } @@ -100,8 +95,8 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::Refresh() { - this->registered_program_redirector.ClearRedirections(); - this->registered_html_docs_redirector.ClearRedirections(); + this->registered_program_locations.Clear(); + this->registered_html_docs_locations.Clear(); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index 3c40f9462..cc0516272 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -19,6 +19,7 @@ #include #include "impl/lr_redirection.hpp" +#include "impl/lr_registered_data.hpp" #include "lr_types.hpp" namespace sts::lr { @@ -38,11 +39,10 @@ namespace sts::lr { }; private: impl::LocationRedirector program_redirector; - impl::RegisteredLocationRedirector registered_program_redirector; + impl::RegisteredLocations registered_program_locations; impl::LocationRedirector html_docs_redirector; - impl::RegisteredLocationRedirector registered_html_docs_redirector; + impl::RegisteredLocations registered_html_docs_locations; public: - RegisteredLocationResolverInterface(); ~RegisteredLocationResolverInterface(); Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); From a310e52cdcd4504103906322183ab1e7cd4c8f70 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 23:00:45 +1000 Subject: [PATCH 46/58] Reorder stratosphere Makefile --- stratosphere/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 8a858beb3..b0511079c 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -MODULES := loader pm sm boot ams_mitm spl eclct.stub ro creport fatal dmnt ncm +MODULES := loader ncm pm sm boot ams_mitm spl eclct.stub ro creport fatal dmnt SUBFOLDERS := libstratosphere $(MODULES) From 742e474f68e1882f227de3d11a68d30084e08ccb Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 23:09:04 +1000 Subject: [PATCH 47/58] Move results to libstrat --- .../stratosphere/results/fs_results.hpp | 69 ++++++++++--------- .../stratosphere/results/lr_results.hpp | 1 + .../stratosphere/results/ncm_results.hpp | 5 ++ stratosphere/ncm/source/lr_types.hpp | 2 - stratosphere/ncm/source/ncm_types.hpp | 10 --- 5 files changed, 43 insertions(+), 44 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/results/fs_results.hpp b/stratosphere/libstratosphere/include/stratosphere/results/fs_results.hpp index 4bb0b89a0..8dd66d3d9 100644 --- a/stratosphere/libstratosphere/include/stratosphere/results/fs_results.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/results/fs_results.hpp @@ -19,49 +19,54 @@ static constexpr u32 Module_Fs = 2; -static constexpr Result ResultFsPathNotFound = MAKERESULT(Module_Fs, 1); -static constexpr Result ResultFsPathAlreadyExists = MAKERESULT(Module_Fs, 2); +static constexpr Result ResultFsPathNotFound = MAKERESULT(Module_Fs, 1); +static constexpr Result ResultFsPathAlreadyExists = MAKERESULT(Module_Fs, 2); -static constexpr Result ResultFsTargetLocked = MAKERESULT(Module_Fs, 7); -static constexpr Result ResultFsDirectoryNotEmpty = MAKERESULT(Module_Fs, 8); +static constexpr Result ResultFsTargetLocked = MAKERESULT(Module_Fs, 7); +static constexpr Result ResultFsDirectoryNotEmpty = MAKERESULT(Module_Fs, 8); -static constexpr Result ResultFsNotEnoughFreeSpaceRangeStart = MAKERESULT(Module_Fs, 30); - static constexpr Result ResultFsNotEnoughFreeSpaceBisRangeStart = MAKERESULT(Module_Fs, 34); - static constexpr Result ResultFsNotEnoughFreeSpaceBisCalibration = MAKERESULT(Module_Fs, 35); - static constexpr Result ResultFsNotEnoughFreeSpaceBisSafe = MAKERESULT(Module_Fs, 36); - static constexpr Result ResultFsNotEnoughFreeSpaceBisUser = MAKERESULT(Module_Fs, 37); - static constexpr Result ResultFsNotEnoughFreeSpaceBisSystem = MAKERESULT(Module_Fs, 38); - static constexpr Result ResultFsNotEnoughFreeSpaceBisRangeEnd = MAKERESULT(Module_Fs, 39); - static constexpr Result ResultFsNotEnoughFreeSpaceSdCard = MAKERESULT(Module_Fs, 39); -static constexpr Result ResultFsNotEnoughFreeSpaceRangeEnd = MAKERESULT(Module_Fs, 45); +static constexpr Result ResultFsNotEnoughFreeSpaceRangeStart = MAKERESULT(Module_Fs, 30); + static constexpr Result ResultFsNotEnoughFreeSpaceBisRangeStart = MAKERESULT(Module_Fs, 34); + static constexpr Result ResultFsNotEnoughFreeSpaceBisCalibration = MAKERESULT(Module_Fs, 35); + static constexpr Result ResultFsNotEnoughFreeSpaceBisSafe = MAKERESULT(Module_Fs, 36); + static constexpr Result ResultFsNotEnoughFreeSpaceBisUser = MAKERESULT(Module_Fs, 37); + static constexpr Result ResultFsNotEnoughFreeSpaceBisSystem = MAKERESULT(Module_Fs, 38); + static constexpr Result ResultFsNotEnoughFreeSpaceBisRangeEnd = MAKERESULT(Module_Fs, 39); + static constexpr Result ResultFsNotEnoughFreeSpaceSdCard = MAKERESULT(Module_Fs, 39); +static constexpr Result ResultFsNotEnoughFreeSpaceRangeEnd = MAKERESULT(Module_Fs, 45); -static constexpr Result ResultFsMountNameAlreadyExists = MAKERESULT(Module_Fs, 60); +static constexpr Result ResultFsMountNameAlreadyExists = MAKERESULT(Module_Fs, 60); -static constexpr Result ResultFsTargetNotFound = MAKERESULT(Module_Fs, 1002); +static constexpr Result ResultFsTargetNotFound = MAKERESULT(Module_Fs, 1002); -static constexpr Result ResultFsSdCardNotPresent = MAKERESULT(Module_Fs, 2001); +static constexpr Result ResultFsSdCardNotPresent = MAKERESULT(Module_Fs, 2001); -static constexpr Result ResultFsNotImplemented = MAKERESULT(Module_Fs, 3001); -static constexpr Result ResultFsOutOfRange = MAKERESULT(Module_Fs, 3005); +static constexpr Result ResultFsNotImplemented = MAKERESULT(Module_Fs, 3001); +static constexpr Result ResultFsOutOfRange = MAKERESULT(Module_Fs, 3005); static constexpr Result ResultFsAllocationFailureInDirectorySaveDataFileSystem = MAKERESULT(Module_Fs, 3321); static constexpr Result ResultFsAllocationFailureInSubDirectoryFileSystem = MAKERESULT(Module_Fs, 3355); -static constexpr Result ResultFsPreconditionViolation = MAKERESULT(Module_Fs, 6000); -static constexpr Result ResultFsInvalidArgument = MAKERESULT(Module_Fs, 6001); -static constexpr Result ResultFsInvalidPath = MAKERESULT(Module_Fs, 6002); -static constexpr Result ResultFsTooLongPath = MAKERESULT(Module_Fs, 6003); -static constexpr Result ResultFsInvalidCharacter = MAKERESULT(Module_Fs, 6004); -static constexpr Result ResultFsInvalidPathFormat = MAKERESULT(Module_Fs, 6005); -static constexpr Result ResultFsDirectoryUnobtainable = MAKERESULT(Module_Fs, 6006); -static constexpr Result ResultFsNotNormalized = MAKERESULT(Module_Fs, 6007); +static constexpr Result ResultFsPreconditionViolation = MAKERESULT(Module_Fs, 6000); +static constexpr Result ResultFsInvalidArgument = MAKERESULT(Module_Fs, 6001); +static constexpr Result ResultFsInvalidPath = MAKERESULT(Module_Fs, 6002); +static constexpr Result ResultFsTooLongPath = MAKERESULT(Module_Fs, 6003); +static constexpr Result ResultFsInvalidCharacter = MAKERESULT(Module_Fs, 6004); +static constexpr Result ResultFsInvalidPathFormat = MAKERESULT(Module_Fs, 6005); +static constexpr Result ResultFsDirectoryUnobtainable = MAKERESULT(Module_Fs, 6006); +static constexpr Result ResultFsNotNormalized = MAKERESULT(Module_Fs, 6007); -static constexpr Result ResultFsInvalidOffset = MAKERESULT(Module_Fs, 6061); -static constexpr Result ResultFsInvalidSize = MAKERESULT(Module_Fs, 6062); -static constexpr Result ResultFsNullptrArgument = MAKERESULT(Module_Fs, 6063); +static constexpr Result ResultFsInvalidOffset = MAKERESULT(Module_Fs, 6061); +static constexpr Result ResultFsInvalidSize = MAKERESULT(Module_Fs, 6062); +static constexpr Result ResultFsNullptrArgument = MAKERESULT(Module_Fs, 6063); +static constexpr Result ResultFsInvalidMountName = MAKERESULT(Module_Fs, 6065); -static constexpr Result ResultFsInvalidSaveDataSpaceId = MAKERESULT(Module_Fs, 6082); +static constexpr Result ResultFsInvalidSaveDataSpaceId = MAKERESULT(Module_Fs, 6082); -static constexpr Result ResultFsUnsupportedOperation = MAKERESULT(Module_Fs, 6300); +static constexpr Result ResultFsFileExtensionWithoutOpenModeAllowAppend = MAKERESULT(Module_Fs, 6201); -static constexpr Result ResultFsPermissionDenied = MAKERESULT(Module_Fs, 6400); +static constexpr Result ResultFsUnsupportedOperation = MAKERESULT(Module_Fs, 6300); + +static constexpr Result ResultFsPermissionDenied = MAKERESULT(Module_Fs, 6400); + +static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); diff --git a/stratosphere/libstratosphere/include/stratosphere/results/lr_results.hpp b/stratosphere/libstratosphere/include/stratosphere/results/lr_results.hpp index 5b2a01b97..a463ceedf 100644 --- a/stratosphere/libstratosphere/include/stratosphere/results/lr_results.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/results/lr_results.hpp @@ -26,5 +26,6 @@ static constexpr Result ResultLrHtmlDocumentNotFound = MAKER static constexpr Result ResultLrAddOnContentNotFound = MAKERESULT(Module_Lr, 7); static constexpr Result ResultLrControlNotFound = MAKERESULT(Module_Lr, 8); static constexpr Result ResultLrLegalInformationNotFound = MAKERESULT(Module_Lr, 9); +static constexpr Result ResultLrDebugProgramNotFound = MAKERESULT(Module_Lr, 10); static constexpr Result ResultLrTooManyRegisteredPaths = MAKERESULT(Module_Lr, 90); diff --git a/stratosphere/libstratosphere/include/stratosphere/results/ncm_results.hpp b/stratosphere/libstratosphere/include/stratosphere/results/ncm_results.hpp index 87cc115e9..6455921df 100644 --- a/stratosphere/libstratosphere/include/stratosphere/results/ncm_results.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/results/ncm_results.hpp @@ -19,6 +19,7 @@ static constexpr u32 Module_Ncm = 5; +static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); static constexpr Result ResultNcmPlaceHolderAlreadyExists = MAKERESULT(Module_Ncm, 2); static constexpr Result ResultNcmPlaceHolderNotFound = MAKERESULT(Module_Ncm, 3); static constexpr Result ResultNcmContentAlreadyExists = MAKERESULT(Module_Ncm, 4); @@ -30,7 +31,9 @@ static constexpr Result ResultNcmUnknownStorage = MAKER static constexpr Result ResultNcmInvalidContentStorage = MAKERESULT(Module_Ncm, 100); static constexpr Result ResultNcmInvalidContentMetaDatabase = MAKERESULT(Module_Ncm, 110); +static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); static constexpr Result ResultNcmBufferInsufficient = MAKERESULT(Module_Ncm, 180); +static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); static constexpr Result ResultNcmInvalidContentMetaKey = MAKERESULT(Module_Ncm, 240); static constexpr Result ResultNcmContentStorageNotActive = MAKERESULT(Module_Ncm, 250); @@ -47,5 +50,7 @@ static constexpr Result ResultNcmNandUserContentMetaDatabaseNotActive = MAKER static constexpr Result ResultNcmSdCardContentMetaDatabaseNotActive = MAKERESULT(Module_Ncm, 264); static constexpr Result ResultNcmUnknownContentMetaDatabaseNotActive = MAKERESULT(Module_Ncm, 268); +static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); + static constexpr Result ResultNcmInvalidArgument = MAKERESULT(Module_Ncm, 8181); static constexpr Result ResultNcmInvalidOffset = MAKERESULT(Module_Ncm, 8182); diff --git a/stratosphere/ncm/source/lr_types.hpp b/stratosphere/ncm/source/lr_types.hpp index 9d921aa45..e0d7df167 100644 --- a/stratosphere/ncm/source/lr_types.hpp +++ b/stratosphere/ncm/source/lr_types.hpp @@ -110,6 +110,4 @@ namespace sts::lr { } }; - static constexpr Result ResultLrDebugProgramNotFound = MAKERESULT(Module_Lr, 10); - } \ No newline at end of file diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 8264c4f06..72b48ad3b 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -198,14 +198,4 @@ namespace sts::ncm { typedef void (*MakeContentPathFunc)(char* out, ContentId content_id, const char* root); typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); - // TODO: Move to libstrat - static constexpr Result ResultNcmStoragePathNotFound = MAKERESULT(Module_Ncm, 1); - static constexpr Result ResultNcmInvalidPlaceHolderDirectoryEntry = MAKERESULT(Module_Ncm, 170); - static constexpr Result ResultNcmInvalidContentStorageOperation = MAKERESULT(Module_Ncm, 190); - static constexpr Result ResultNcmStorageRootNotFound = MAKERESULT(Module_Ncm, 310); - - static constexpr Result ResultFsFileExtensionWithoutOpenModeAllowAppend = MAKERESULT(Module_Fs, 6201); - static constexpr Result ResultFsInvalidMountName = MAKERESULT(Module_Fs, 6065); - static constexpr Result ResultFsMountNameNotFound = MAKERESULT(Module_Fs, 6905); - } \ No newline at end of file From f62174abfddb98574b66c31309ea8dabd1569fcd Mon Sep 17 00:00:00 2001 From: Adubbz Date: Tue, 13 Aug 2019 23:38:24 +1000 Subject: [PATCH 48/58] lr: Cleanup lr_redirection --- .../ncm/source/impl/lr_redirection.cpp | 65 ++++++++++++------- .../ncm/source/impl/lr_redirection.hpp | 16 +---- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/stratosphere/ncm/source/impl/lr_redirection.cpp b/stratosphere/ncm/source/impl/lr_redirection.cpp index 9af961411..e69e09ba3 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.cpp +++ b/stratosphere/ncm/source/impl/lr_redirection.cpp @@ -18,54 +18,75 @@ namespace sts::lr::impl { + class LocationRedirection : public util::IntrusiveListBaseNode { + NON_COPYABLE(LocationRedirection); + NON_MOVEABLE(LocationRedirection); + private: + ncm::TitleId title_id; + Path path; + u32 flags; + public: + LocationRedirection(ncm::TitleId title_id, const Path& path, u32 flags) : + title_id(title_id), path(path), flags(flags) { /* ... */ } + + ncm::TitleId GetTitleId() const { + return this->title_id; + } + + void GetPath(Path *out) const { + *out = this->path; + } + + u32 GetFlags() const { + return this->flags; + } + + void SetFlags(u32 flags) { + this->flags = flags; + } + }; + bool LocationRedirector::FindRedirection(Path *out, ncm::TitleId title_id) { if (this->redirection_list.empty()) { return false; } - for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { - if (it->title_id == title_id) { - *out = it->path; + for (const auto &redirection : this->redirection_list) { + if (redirection.GetTitleId() == title_id) { + redirection.GetPath(out); return true; } } - return false; } void LocationRedirector::SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags) { this->EraseRedirection(title_id); - auto redirection = new LocationRedirection(title_id, path, flags); - this->redirection_list.push_back(*redirection); + this->redirection_list.push_back(*(new LocationRedirection(title_id, path, flags))); } void LocationRedirector::SetRedirectionFlags(ncm::TitleId title_id, u32 flags) { - if (!this->redirection_list.empty()) { - for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { - if (it->title_id == title_id) { - it->flags = flags; - break; - } + for (auto &redirection : this->redirection_list) { + if (redirection.GetTitleId() == title_id) { + redirection.SetFlags(flags); + break; } } } void LocationRedirector::EraseRedirection(ncm::TitleId title_id) { - if (!this->redirection_list.empty()) { - for (auto it = this->redirection_list.begin(); it != this->redirection_list.end(); it++) { - if (it->title_id == title_id) { - auto old = it; - this->redirection_list.erase(old); - delete &(*old); - break; - } + for (auto &redirection : this->redirection_list) { + if (redirection.GetTitleId() == title_id) { + this->redirection_list.erase(this->redirection_list.iterator_to(redirection)); + delete &redirection; + break; } } } void LocationRedirector::ClearRedirections(u32 flags) { for (auto it = this->redirection_list.begin(); it != this->redirection_list.end();) { - if ((it->flags & flags) == flags) { + if ((it->GetFlags() & flags) == flags) { auto old = it; it = this->redirection_list.erase(it); delete &(*old); @@ -75,6 +96,4 @@ namespace sts::lr::impl { } } - - } \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index fccd85c0d..2d182137d 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -27,19 +27,7 @@ namespace sts::lr::impl { RedirectionFlags_Application = (1 << 0), }; - class LocationRedirection : public util::IntrusiveListBaseNode { - NON_COPYABLE(LocationRedirection); - NON_MOVEABLE(LocationRedirection); - - public: - ncm::TitleId title_id; - Path path; - u32 flags; - - LocationRedirection(ncm::TitleId title_id, const Path& path, u32 flags) : - title_id(title_id), path(path), flags(flags) { - } - }; + class LocationRedirection; class LocationRedirector { NON_COPYABLE(LocationRedirector); @@ -47,7 +35,7 @@ namespace sts::lr::impl { private: sts::util::IntrusiveListBaseTraits::ListType redirection_list; public: - LocationRedirector() {} + LocationRedirector() { /* ... */ } bool FindRedirection(Path *out, ncm::TitleId title_id); void SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags = RedirectionFlags_None); From 8278bda54ecfbf865076acdc7e771868240acb60 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 18:17:01 +1000 Subject: [PATCH 49/58] lr: lr_manager tweaks --- .../stratosphere/ipc/ipc_domain_object.hpp | 4 ++++ stratosphere/ncm/source/impl/lr_manager.cpp | 20 +++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp index 3cc9cbca2..ba8c25b7a 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp @@ -127,4 +127,8 @@ class Out> : public OutSessionTag { void SetValue(std::shared_ptr &&s) { *this->srv = std::move(s); } + + void SetValue(std::shared_ptr &s) { + *this->srv = s; + } }; diff --git a/stratosphere/ncm/source/impl/lr_manager.cpp b/stratosphere/ncm/source/impl/lr_manager.cpp index 2b8134f41..38144661d 100644 --- a/stratosphere/ncm/source/impl/lr_manager.cpp +++ b/stratosphere/ncm/source/impl/lr_manager.cpp @@ -41,11 +41,10 @@ namespace sts::lr::impl { R_TRY(content_resolver->Refresh()); g_location_resolvers[storage_id] = std::move(content_resolver); } + resolver = g_location_resolvers.Find(storage_id); } - /* Make a copy of the resolver for output. */ - auto tmp_resolver = g_location_resolvers[storage_id]; - out.SetValue(std::move(tmp_resolver)); + out.SetValue(*resolver); return ResultSuccess; } @@ -55,10 +54,8 @@ namespace sts::lr::impl { if (!g_registered_location_resolver) { g_registered_location_resolver = std::make_shared(); } - - /* Make a copy of the resolver for output. */ - auto tmp_resolver = g_registered_location_resolver; - out.SetValue(std::move(tmp_resolver)); + + out.SetValue(g_registered_location_resolver); return ResultSuccess; } @@ -70,7 +67,10 @@ namespace sts::lr::impl { return ResultLrUnknownStorageId; } - (*resolver)->Refresh(); + if (storage_id != ncm::StorageId::Host) { + (*resolver)->Refresh(); + } + return ResultSuccess; } @@ -81,9 +81,7 @@ namespace sts::lr::impl { g_add_on_content_location_resolver = std::make_shared(); } - /* Make a copy of the resolver for output. */ - auto tmp_resolver = g_add_on_content_location_resolver; - out.SetValue(std::move(tmp_resolver)); + out.SetValue(g_add_on_content_location_resolver); return ResultSuccess; } From 6f99b0bf2b1877abaf1ec165ba59d26fede1e9f1 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 20:13:21 +1000 Subject: [PATCH 50/58] lr: Imrpoved path handling and adjust ResolveAddOnContentPath order --- .../ncm/source/lr_addoncontentlocationresolver.cpp | 9 +++++---- stratosphere/ncm/source/lr_types.hpp | 11 ++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 4f346968d..3179f7f12 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -28,12 +28,13 @@ namespace sts::lr { } std::shared_ptr content_meta_database; - std::shared_ptr content_storage; - R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); - R_TRY(ncm::impl::OpenContentStorage(&content_storage, storage_id)); - + ncm::ContentId data_content_id; + R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, storage_id)); R_TRY(content_meta_database->GetLatestData(&data_content_id, tid)); + + std::shared_ptr content_storage; + R_TRY(ncm::impl::OpenContentStorage(&content_storage, storage_id)); R_ASSERT(content_storage->GetPath(&path, data_content_id)); *out.pointer = path; diff --git a/stratosphere/ncm/source/lr_types.hpp b/stratosphere/ncm/source/lr_types.hpp index e0d7df167..1c523acd8 100644 --- a/stratosphere/ncm/source/lr_types.hpp +++ b/stratosphere/ncm/source/lr_types.hpp @@ -30,22 +30,19 @@ namespace sts::lr { } Path(const char* path) { - strlcpy(this->path, path, MaxPathLen); + strncpy(this->path, path, MaxPathLen-1); + this->EnsureNullTerminated(); } Path& operator=(const Path& other) { /* N appears to always memcpy paths, so we will too. */ - memcpy(this->path, other.path, MaxPathLen); + std::memcpy(this->path, other.path, MaxPathLen); this->EnsureNullTerminated(); return *this; } void EnsureNullTerminated() { - const size_t len = strnlen(this->path, MaxPathLen); - - if (len == MaxPathLen) { - path[MaxPathLen-1] = '\0'; - } + path[MaxPathLen-1] = '\0'; } }; From f044c52e7de34f9226cbbb230e34b380d09651bd Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 20:24:11 +1000 Subject: [PATCH 51/58] lr: Organise types --- .../libstratosphere/include/stratosphere.hpp | 1 + .../include/stratosphere/lr.hpp | 20 ++++++++ .../include/stratosphere/lr/lr_types.hpp | 49 +++++++++++++++++++ stratosphere/ncm/source/impl/lr_manager.cpp | 3 +- .../ncm/source/impl/lr_redirection.hpp | 2 - .../ncm/source/impl/lr_registered_data.hpp | 2 - .../ncm_bounded_map.hpp} | 32 ++---------- .../lr_addoncontentlocationresolver.hpp | 1 - .../source/lr_registeredlocationresolver.hpp | 1 - .../ncm/source/ncm_icontentstorage.hpp | 1 - 10 files changed, 75 insertions(+), 37 deletions(-) create mode 100644 stratosphere/libstratosphere/include/stratosphere/lr.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/lr/lr_types.hpp rename stratosphere/ncm/source/{lr_types.hpp => impl/ncm_bounded_map.hpp} (79%) diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index 78832a5de..f40b22ba2 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -47,6 +47,7 @@ #include "stratosphere/cfg.hpp" #include "stratosphere/fatal.hpp" #include "stratosphere/hid.hpp" +#include "stratosphere/lr.hpp" #include "stratosphere/ncm.hpp" #include "stratosphere/pm.hpp" #include "stratosphere/rnd.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/lr.hpp b/stratosphere/libstratosphere/include/stratosphere/lr.hpp new file mode 100644 index 000000000..51ea02934 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/lr.hpp @@ -0,0 +1,20 @@ +/* + * 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 . + */ + +#pragma once +#include + +#include "lr/lr_types.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/lr/lr_types.hpp b/stratosphere/libstratosphere/include/stratosphere/lr/lr_types.hpp new file mode 100644 index 000000000..e845201d9 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/lr/lr_types.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Adubbz + * + * 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 . + */ + +#pragma once +#include +#include + +namespace sts::lr { + + constexpr size_t MaxPathLen = 0x300; + + struct Path { + char path[MaxPathLen]; + + Path() { + path[0] = '\0'; + } + + Path(const char* path) { + strncpy(this->path, path, MaxPathLen-1); + this->EnsureNullTerminated(); + } + + Path& operator=(const Path& other) { + /* N appears to always memcpy paths, so we will too. */ + std::memcpy(this->path, other.path, MaxPathLen); + this->EnsureNullTerminated(); + return *this; + } + + void EnsureNullTerminated() { + path[MaxPathLen-1] = '\0'; + } + }; + +} diff --git a/stratosphere/ncm/source/impl/lr_manager.cpp b/stratosphere/ncm/source/impl/lr_manager.cpp index 38144661d..356808c8f 100644 --- a/stratosphere/ncm/source/impl/lr_manager.cpp +++ b/stratosphere/ncm/source/impl/lr_manager.cpp @@ -17,12 +17,13 @@ #include "../lr_contentlocationresolver.hpp" #include "../lr_redirectonlylocationresolver.hpp" #include "lr_manager.hpp" +#include "ncm_bounded_map.hpp" namespace sts::lr::impl { namespace { - BoundedMap, 5> g_location_resolvers; + ncm::impl::BoundedMap, 5> g_location_resolvers; std::shared_ptr g_registered_location_resolver = nullptr; std::shared_ptr g_add_on_content_location_resolver = nullptr; HosMutex g_mutex; diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index 2d182137d..3aa97ee09 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -18,8 +18,6 @@ #include #include -#include "../lr_types.hpp" - namespace sts::lr::impl { enum RedirectionFlags { diff --git a/stratosphere/ncm/source/impl/lr_registered_data.hpp b/stratosphere/ncm/source/impl/lr_registered_data.hpp index 5d54b8e16..7217a946d 100644 --- a/stratosphere/ncm/source/impl/lr_registered_data.hpp +++ b/stratosphere/ncm/source/impl/lr_registered_data.hpp @@ -18,8 +18,6 @@ #include #include -#include "../lr_types.hpp" - namespace sts::lr::impl { template diff --git a/stratosphere/ncm/source/lr_types.hpp b/stratosphere/ncm/source/impl/ncm_bounded_map.hpp similarity index 79% rename from stratosphere/ncm/source/lr_types.hpp rename to stratosphere/ncm/source/impl/ncm_bounded_map.hpp index 1c523acd8..e2b5d6d6a 100644 --- a/stratosphere/ncm/source/lr_types.hpp +++ b/stratosphere/ncm/source/impl/ncm_bounded_map.hpp @@ -18,34 +18,8 @@ #include #include -namespace sts::lr { - - constexpr size_t MaxPathLen = 0x300; - - struct Path { - char path[MaxPathLen]; - - Path() { - path[0] = '\0'; - } - - Path(const char* path) { - strncpy(this->path, path, MaxPathLen-1); - this->EnsureNullTerminated(); - } - - Path& operator=(const Path& other) { - /* N appears to always memcpy paths, so we will too. */ - std::memcpy(this->path, other.path, MaxPathLen); - this->EnsureNullTerminated(); - return *this; - } - - void EnsureNullTerminated() { - path[MaxPathLen-1] = '\0'; - } - }; - +namespace sts::ncm::impl { + template class BoundedMap { private: @@ -107,4 +81,4 @@ namespace sts::lr { } }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp index cb9056b6d..320f651c0 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp @@ -19,7 +19,6 @@ #include #include "impl/lr_registered_data.hpp" -#include "lr_types.hpp" namespace sts::lr { diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index cc0516272..97a5bc49a 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -20,7 +20,6 @@ #include "impl/lr_redirection.hpp" #include "impl/lr_registered_data.hpp" -#include "lr_types.hpp" namespace sts::lr { diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index 3e1d1d1f6..626787797 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -18,7 +18,6 @@ #include #include -#include "lr_types.hpp" #include "ncm_types.hpp" namespace sts::ncm { From c20d123f6038aaba22311a9a774438e50804c8a4 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 20:29:46 +1000 Subject: [PATCH 52/58] Add eof newlines --- stratosphere/ncm/source/impl/lr_manager.cpp | 2 +- stratosphere/ncm/source/impl/lr_manager.hpp | 2 +- stratosphere/ncm/source/impl/lr_redirection.cpp | 2 +- stratosphere/ncm/source/impl/lr_redirection.hpp | 2 +- stratosphere/ncm/source/impl/lr_registered_data.hpp | 2 +- stratosphere/ncm/source/impl/ncm_content_manager.cpp | 2 +- stratosphere/ncm/source/impl/ncm_content_manager.hpp | 2 +- stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp | 2 +- stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp | 2 +- stratosphere/ncm/source/impl/ncm_rights_cache.cpp | 2 +- stratosphere/ncm/source/impl/ncm_rights_cache.hpp | 2 +- stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp | 2 +- stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp | 2 +- stratosphere/ncm/source/lr_contentlocationresolver.cpp | 2 +- stratosphere/ncm/source/lr_contentlocationresolver.hpp | 5 ++--- stratosphere/ncm/source/lr_ilocationresolver.cpp | 2 +- stratosphere/ncm/source/lr_ilocationresolver.hpp | 2 +- stratosphere/ncm/source/lr_manager_service.cpp | 2 +- stratosphere/ncm/source/lr_manager_service.hpp | 2 +- stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp | 2 +- stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp | 2 +- stratosphere/ncm/source/lr_registeredlocationresolver.cpp | 2 +- stratosphere/ncm/source/lr_registeredlocationresolver.hpp | 2 +- stratosphere/ncm/source/ncm_content_manager_service.cpp | 2 +- stratosphere/ncm/source/ncm_content_manager_service.hpp | 2 +- stratosphere/ncm/source/ncm_contentmetadatabase.cpp | 2 +- stratosphere/ncm/source/ncm_contentmetadatabase.hpp | 2 +- stratosphere/ncm/source/ncm_contentstorage.cpp | 2 +- stratosphere/ncm/source/ncm_contentstorage.hpp | 2 +- stratosphere/ncm/source/ncm_fs.cpp | 2 +- stratosphere/ncm/source/ncm_fs.hpp | 2 +- stratosphere/ncm/source/ncm_icontentmetadatabase.cpp | 2 +- stratosphere/ncm/source/ncm_icontentmetadatabase.hpp | 2 +- stratosphere/ncm/source/ncm_icontentstorage.cpp | 2 +- stratosphere/ncm/source/ncm_icontentstorage.hpp | 2 +- stratosphere/ncm/source/ncm_main.cpp | 2 +- stratosphere/ncm/source/ncm_make_path.cpp | 2 +- stratosphere/ncm/source/ncm_make_path.hpp | 2 +- stratosphere/ncm/source/ncm_path_utils.cpp | 2 +- stratosphere/ncm/source/ncm_path_utils.hpp | 2 +- stratosphere/ncm/source/ncm_readonlycontentstorage.cpp | 2 +- stratosphere/ncm/source/ncm_readonlycontentstorage.hpp | 2 +- stratosphere/ncm/source/ncm_types.hpp | 2 +- stratosphere/ncm/source/ncm_utils.cpp | 2 +- stratosphere/ncm/source/ncm_utils.hpp | 2 +- 45 files changed, 46 insertions(+), 47 deletions(-) diff --git a/stratosphere/ncm/source/impl/lr_manager.cpp b/stratosphere/ncm/source/impl/lr_manager.cpp index 356808c8f..da5ab775d 100644 --- a/stratosphere/ncm/source/impl/lr_manager.cpp +++ b/stratosphere/ncm/source/impl/lr_manager.cpp @@ -86,4 +86,4 @@ namespace sts::lr::impl { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/lr_manager.hpp b/stratosphere/ncm/source/impl/lr_manager.hpp index c9473b973..865bb8189 100644 --- a/stratosphere/ncm/source/impl/lr_manager.hpp +++ b/stratosphere/ncm/source/impl/lr_manager.hpp @@ -30,4 +30,4 @@ namespace sts::lr::impl { Result RefreshLocationResolver(ncm::StorageId storage_id); Result OpenAddOnContentLocationResolver(Out> out); -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/lr_redirection.cpp b/stratosphere/ncm/source/impl/lr_redirection.cpp index e69e09ba3..21e9c63ac 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.cpp +++ b/stratosphere/ncm/source/impl/lr_redirection.cpp @@ -96,4 +96,4 @@ namespace sts::lr::impl { } } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index 3aa97ee09..d31693219 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -42,4 +42,4 @@ namespace sts::lr::impl { void ClearRedirections(u32 flags = RedirectionFlags_None); }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/lr_registered_data.hpp b/stratosphere/ncm/source/impl/lr_registered_data.hpp index 7217a946d..456708074 100644 --- a/stratosphere/ncm/source/impl/lr_registered_data.hpp +++ b/stratosphere/ncm/source/impl/lr_registered_data.hpp @@ -94,4 +94,4 @@ namespace sts::lr::impl { template using RegisteredStorages = RegisteredData; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index bce0f1f5a..28e1b80ee 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -706,4 +706,4 @@ namespace sts::ncm::impl { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.hpp b/stratosphere/ncm/source/impl/ncm_content_manager.hpp index 17423a542..7cfe4254e 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.hpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.hpp @@ -44,4 +44,4 @@ namespace sts::ncm::impl { Result ActivateContentMetaDatabase(StorageId storage_id); Result InactivateContentMetaDatabase(StorageId storage_id); -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index 3c600434e..ae367f2e6 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -235,4 +235,4 @@ namespace sts::ncm::impl { } } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index 73debc2da..fd43a8b37 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -76,4 +76,4 @@ namespace sts::ncm::impl { void InvalidateAll(); }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.cpp b/stratosphere/ncm/source/impl/ncm_rights_cache.cpp index 14c314884..42b57da7c 100644 --- a/stratosphere/ncm/source/impl/ncm_rights_cache.cpp +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.cpp @@ -28,4 +28,4 @@ namespace sts::ncm::impl { return &g_rights_id_cache; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp index 1d09617ca..9750c2a13 100644 --- a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp @@ -41,4 +41,4 @@ namespace sts::ncm::impl { RightsIdCache* GetRightsIdCache(); -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 3179f7f12..9fc4b5cae 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -54,4 +54,4 @@ namespace sts::lr { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp index 320f651c0..16febe352 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp @@ -43,4 +43,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 95680e8bd..6bebe6bca 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -195,4 +195,4 @@ namespace sts::lr { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.hpp b/stratosphere/ncm/source/lr_contentlocationresolver.hpp index e5a59370c..ee4667d51 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.hpp @@ -31,8 +31,7 @@ namespace sts::lr { std::shared_ptr content_meta_database; std::shared_ptr content_storage; public: - ContentLocationResolverInterface(ncm::StorageId storage_id) : storage_id(storage_id) { - } + ContentLocationResolverInterface(ncm::StorageId storage_id) : storage_id(storage_id) { /* ... */ } ~ContentLocationResolverInterface(); public: @@ -81,4 +80,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_ilocationresolver.cpp b/stratosphere/ncm/source/lr_ilocationresolver.cpp index ef9bcf71f..68b0e2d6a 100644 --- a/stratosphere/ncm/source/lr_ilocationresolver.cpp +++ b/stratosphere/ncm/source/lr_ilocationresolver.cpp @@ -98,4 +98,4 @@ namespace sts::lr { std::abort(); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_ilocationresolver.hpp b/stratosphere/ncm/source/lr_ilocationresolver.hpp index 2b4a7bef8..fa669430f 100644 --- a/stratosphere/ncm/source/lr_ilocationresolver.hpp +++ b/stratosphere/ncm/source/lr_ilocationresolver.hpp @@ -98,4 +98,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_manager_service.cpp b/stratosphere/ncm/source/lr_manager_service.cpp index 6958cb11e..01468eb1c 100644 --- a/stratosphere/ncm/source/lr_manager_service.cpp +++ b/stratosphere/ncm/source/lr_manager_service.cpp @@ -36,4 +36,4 @@ namespace sts::lr { return impl::OpenAddOnContentLocationResolver(out); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_manager_service.hpp b/stratosphere/ncm/source/lr_manager_service.hpp index 5a1058346..81b887cfc 100644 --- a/stratosphere/ncm/source/lr_manager_service.hpp +++ b/stratosphere/ncm/source/lr_manager_service.hpp @@ -47,4 +47,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index b140e69b1..2a36c5f3e 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -171,4 +171,4 @@ namespace sts::lr { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp index e69696d18..9346d5d67 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.hpp @@ -71,4 +71,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 5d7af37ff..8e4dea648 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -100,4 +100,4 @@ namespace sts::lr { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index 97a5bc49a..0d6f0f4d7 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -67,4 +67,4 @@ namespace sts::lr { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp index cd95b9191..5a2d3c550 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.cpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp @@ -77,4 +77,4 @@ namespace sts::ncm { return impl::InactivateContentMetaDatabase(storage_id); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_content_manager_service.hpp b/stratosphere/ncm/source/ncm_content_manager_service.hpp index 6b6813158..1d2c2fe31 100644 --- a/stratosphere/ncm/source/ncm_content_manager_service.hpp +++ b/stratosphere/ncm/source/ncm_content_manager_service.hpp @@ -72,4 +72,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 72a46e2e9..6900a1404 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -610,4 +610,4 @@ namespace sts::ncm { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp index b306631e3..1ec7ef2b8 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.hpp @@ -141,4 +141,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index b788659f5..d57ab3e5e 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -655,4 +655,4 @@ namespace sts::ncm { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_contentstorage.hpp b/stratosphere/ncm/source/ncm_contentstorage.hpp index df124f9bd..7f9f8b7de 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.hpp +++ b/stratosphere/ncm/source/ncm_contentstorage.hpp @@ -112,4 +112,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 9eb201e5a..4773c3b0a 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -379,4 +379,4 @@ namespace sts::ncm { return ResultSuccess; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index 347c323fb..1194dbea9 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -113,4 +113,4 @@ namespace sts::ncm { return ResultSuccess; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp index 155b21103..2abb63ede 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.cpp @@ -118,4 +118,4 @@ namespace sts::ncm { std::abort(); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp index 627e0b839..8eed6285c 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -118,4 +118,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_icontentstorage.cpp b/stratosphere/ncm/source/ncm_icontentstorage.cpp index 8eef3d2d3..7ac23e210 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.cpp @@ -138,4 +138,4 @@ namespace sts::ncm { std::abort(); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index 626787797..11b4a0661 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -123,4 +123,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index 14ccc2617..a2fda6ee8 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -164,4 +164,4 @@ int main(int argc, char **argv) sts::ncm::impl::FinalizeContentManager(); return 0; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_make_path.cpp b/stratosphere/ncm/source/ncm_make_path.cpp index d43d89379..d1e82b2cb 100644 --- a/stratosphere/ncm/source/ncm_make_path.cpp +++ b/stratosphere/ncm/source/ncm_make_path.cpp @@ -90,4 +90,4 @@ namespace sts::ncm::path { } } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_make_path.hpp b/stratosphere/ncm/source/ncm_make_path.hpp index 2bd60c849..b8cd03224 100644 --- a/stratosphere/ncm/source/ncm_make_path.hpp +++ b/stratosphere/ncm/source/ncm_make_path.hpp @@ -30,4 +30,4 @@ namespace sts::ncm::path { void MakePlaceHolderPathFlat(char* out_path, PlaceHolderId placeholder_id, const char* root); void MakePlaceHolderPathHashByteLayered(char* out_path, PlaceHolderId placeholder_id, const char* root); -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_path_utils.cpp b/stratosphere/ncm/source/ncm_path_utils.cpp index 57c9458c9..cf51fcbd2 100644 --- a/stratosphere/ncm/source/ncm_path_utils.cpp +++ b/stratosphere/ncm/source/ncm_path_utils.cpp @@ -87,4 +87,4 @@ namespace sts::ncm::path { return this->path.substr(this->path.find_last_of("/") + 1); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_path_utils.hpp b/stratosphere/ncm/source/ncm_path_utils.hpp index cdcd197e0..e538a1aec 100644 --- a/stratosphere/ncm/source/ncm_path_utils.hpp +++ b/stratosphere/ncm/source/ncm_path_utils.hpp @@ -51,4 +51,4 @@ namespace sts::ncm::path { std::string_view GetFileName() const; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index de8dd26b8..0fb32eb5f 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -245,4 +245,4 @@ namespace sts::ncm { return ResultNcmInvalidContentStorageOperation; } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp index 135690230..156eab7fb 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.hpp @@ -88,4 +88,4 @@ namespace sts::ncm { }; }; -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp index 72b48ad3b..44e1192d2 100644 --- a/stratosphere/ncm/source/ncm_types.hpp +++ b/stratosphere/ncm/source/ncm_types.hpp @@ -198,4 +198,4 @@ namespace sts::ncm { typedef void (*MakeContentPathFunc)(char* out, ContentId content_id, const char* root); typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_utils.cpp b/stratosphere/ncm/source/ncm_utils.cpp index a490f6a0f..05f55edaf 100644 --- a/stratosphere/ncm/source/ncm_utils.cpp +++ b/stratosphere/ncm/source/ncm_utils.cpp @@ -78,4 +78,4 @@ namespace sts::ncm { return std::optional(content_id); } -} \ No newline at end of file +} diff --git a/stratosphere/ncm/source/ncm_utils.hpp b/stratosphere/ncm/source/ncm_utils.hpp index 20a00662d..10aeb248a 100644 --- a/stratosphere/ncm/source/ncm_utils.hpp +++ b/stratosphere/ncm/source/ncm_utils.hpp @@ -29,4 +29,4 @@ namespace sts::ncm { Result GetPlaceHolderIdFromDirEntry(PlaceHolderId* out, struct dirent* dir_entry); std::optional GetContentIdFromString(const char* str, size_t len); -}; \ No newline at end of file +}; From e7d2f83ba5466dcfddeca8b428ceef8550945efe Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 20:43:37 +1000 Subject: [PATCH 53/58] lr: Eliminate unnecessary vars --- .../lr_addoncontentlocationresolver.cpp | 4 +-- .../ncm/source/lr_contentlocationresolver.cpp | 35 +++++-------------- .../lr_redirectonlylocationresolver.cpp | 28 ++++----------- .../source/lr_registeredlocationresolver.cpp | 18 ++++------ 4 files changed, 21 insertions(+), 64 deletions(-) diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 9fc4b5cae..78f5fa8a0 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -20,7 +20,6 @@ namespace sts::lr { Result AddOnContentLocationResolverInterface::ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; ncm::StorageId storage_id = ncm::StorageId::None; if (!this->registered_storages.Find(&storage_id, tid)) { @@ -35,8 +34,7 @@ namespace sts::lr { std::shared_ptr content_storage; R_TRY(ncm::impl::OpenContentStorage(&content_storage, storage_id)); - R_ASSERT(content_storage->GetPath(&path, data_content_id)); - *out.pointer = path; + R_ASSERT(content_storage->GetPath(out.pointer, data_content_id)); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 6bebe6bca..807eed5b6 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -28,10 +28,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->program_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->program_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -43,8 +40,7 @@ namespace sts::lr { } } R_END_TRY_CATCH; - R_ASSERT(this->content_storage->GetPath(&path, program_content_id)); - *out.pointer = path; + R_ASSERT(this->content_storage->GetPath(out.pointer, program_content_id)); return ResultSuccess; } @@ -54,10 +50,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->app_control_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->app_control_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -65,10 +58,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->html_docs_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->html_docs_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -76,12 +66,10 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveDataPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); - R_ASSERT(this->content_storage->GetPath(&path, data_content_id)); - *out.pointer = path; + R_ASSERT(this->content_storage->GetPath(out.pointer, data_content_id)); return ResultSuccess; } @@ -96,10 +84,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->legal_info_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->legal_info_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -163,20 +148,16 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->debug_program_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->debug_program_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } - R_TRY_CATCH(this->ResolveProgramPath(&path, tid)) { + R_TRY_CATCH(this->ResolveProgramPath(out.pointer, tid)) { R_CATCH(ResultLrProgramNotFound) { return ResultLrDebugProgramNotFound; } } R_END_TRY_CATCH; - *out.pointer = path; return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 2a36c5f3e..97f8592fd 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -28,10 +28,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->program_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->program_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -44,10 +41,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->app_control_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->app_control_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -55,10 +49,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->html_docs_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->html_docs_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -80,10 +71,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->legal_info_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->legal_info_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } @@ -139,20 +127,16 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (this->debug_program_redirector.FindRedirection(&path, tid)) { - *out.pointer = path; + if (this->debug_program_redirector.FindRedirection(out.pointer, tid)) { return ResultSuccess; } - R_TRY_CATCH(this->ResolveProgramPath(&path, tid)) { + R_TRY_CATCH(this->ResolveProgramPath(out.pointer, tid)) { R_CATCH(ResultLrProgramNotFound) { return ResultLrDebugProgramNotFound; } } R_END_TRY_CATCH; - *out.pointer = path; return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 8e4dea648..4a491f928 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -25,20 +25,17 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (!this->program_redirector.FindRedirection(&path, tid)) { - if (!this->registered_program_locations.Find(&path, tid)) { + if (!this->program_redirector.FindRedirection(out.pointer, tid)) { + if (!this->registered_program_locations.Find(out.pointer, tid)) { return ResultLrProgramNotFound; } } - *out.pointer = path; return ResultSuccess; } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - Path tmp_path = *path.pointer; + const Path& tmp_path = *path.pointer; if (!this->registered_program_locations.Register(tid, tmp_path)) { this->registered_program_locations.Clear(); @@ -60,20 +57,17 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - Path path; - - if (!this->html_docs_redirector.FindRedirection(&path, tid)) { - if (!this->registered_html_docs_locations.Find(&path, tid)) { + if (!this->html_docs_redirector.FindRedirection(out.pointer, tid)) { + if (!this->registered_html_docs_locations.Find(out.pointer, tid)) { return ResultLrProgramNotFound; } } - *out.pointer = path; return ResultLrHtmlDocumentNotFound; } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - Path tmp_path = *path.pointer; + const Path& tmp_path = *path.pointer; if (!this->registered_html_docs_locations.Register(tid, tmp_path)) { this->registered_html_docs_locations.Clear(); From 5acf0be66af425af2a0361fe7bc1b51d90c556d3 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Thu, 15 Aug 2019 20:46:53 +1000 Subject: [PATCH 54/58] lr: Unnecessary vars 2 electric boogaloo --- stratosphere/ncm/source/lr_registeredlocationresolver.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 4a491f928..8e9f53efa 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -51,8 +51,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { - Path tmp_path = *path.pointer; - this->program_redirector.SetRedirection(tid, tmp_path); + this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } @@ -83,8 +82,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - Path tmp_path = *path.pointer; - this->html_docs_redirector.SetRedirection(tid, tmp_path); + this->html_docs_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } From ecd0070e400fe6dab1e7064f2a43860c4219b80a Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 16 Aug 2019 16:19:05 +1000 Subject: [PATCH 55/58] lr: Various helpers --- .../ncm/source/lr_contentlocationresolver.cpp | 38 ++++++++----------- .../ncm/source/lr_contentlocationresolver.hpp | 2 + .../ncm/source/lr_ilocationresolver.hpp | 12 ++++++ .../lr_redirectonlylocationresolver.cpp | 10 ++--- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.cpp b/stratosphere/ncm/source/lr_contentlocationresolver.cpp index 807eed5b6..b8a2bceb7 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.cpp @@ -20,15 +20,15 @@ namespace sts::lr { ContentLocationResolverInterface::~ContentLocationResolverInterface() { - this->program_redirector.ClearRedirections(); - this->debug_program_redirector.ClearRedirections(); - this->app_control_redirector.ClearRedirections(); - this->html_docs_redirector.ClearRedirections(); - this->legal_info_redirector.ClearRedirections(); + this->ClearRedirections(); + } + + void ContentLocationResolverInterface::GetContentStoragePath(Path* out, ncm::ContentId content_id) { + R_ASSERT(this->content_storage->GetPath(out, content_id)); } Result ContentLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->program_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->program_redirector, tid)) { return ResultSuccess; } @@ -40,7 +40,7 @@ namespace sts::lr { } } R_END_TRY_CATCH; - R_ASSERT(this->content_storage->GetPath(out.pointer, program_content_id)); + this->GetContentStoragePath(out.pointer, program_content_id); return ResultSuccess; } @@ -50,7 +50,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->app_control_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->app_control_redirector, tid)) { return ResultSuccess; } @@ -58,7 +58,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->html_docs_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->html_docs_redirector, tid)) { return ResultSuccess; } @@ -69,7 +69,7 @@ namespace sts::lr { ncm::ContentId data_content_id; R_TRY(this->content_meta_database->GetLatestData(&data_content_id, tid)); - R_ASSERT(this->content_storage->GetPath(out.pointer, data_content_id)); + this->GetContentStoragePath(out.pointer, data_content_id); return ResultSuccess; } @@ -84,7 +84,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->legal_info_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->legal_info_redirector, tid)) { return ResultSuccess; } @@ -99,16 +99,12 @@ namespace sts::lr { Result ContentLocationResolverInterface::Refresh() { std::shared_ptr content_meta_database; std::shared_ptr content_storage; + R_TRY(ncm::impl::OpenContentMetaDatabase(&content_meta_database, this->storage_id)); R_TRY(ncm::impl::OpenContentStorage(&content_storage, this->storage_id)); this->content_meta_database = std::move(content_meta_database); this->content_storage = std::move(content_storage); - - this->program_redirector.ClearRedirections(); - this->debug_program_redirector.ClearRedirections(); - this->app_control_redirector.ClearRedirections(); - this->html_docs_redirector.ClearRedirections(); - this->legal_info_redirector.ClearRedirections(); + this->ClearRedirections(); return ResultSuccess; } @@ -119,11 +115,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ClearApplicationRedirection() { - this->program_redirector.ClearRedirections(impl::RedirectionFlags_Application); - this->debug_program_redirector.ClearRedirections(impl::RedirectionFlags_Application); - this->app_control_redirector.ClearRedirections(impl::RedirectionFlags_Application); - this->html_docs_redirector.ClearRedirections(impl::RedirectionFlags_Application); - this->legal_info_redirector.ClearRedirections(impl::RedirectionFlags_Application); + this->ClearRedirections(impl::RedirectionFlags_Application); return ResultSuccess; } @@ -148,7 +140,7 @@ namespace sts::lr { } Result ContentLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->debug_program_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->debug_program_redirector, tid)) { return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_contentlocationresolver.hpp b/stratosphere/ncm/source/lr_contentlocationresolver.hpp index ee4667d51..d7146fadd 100644 --- a/stratosphere/ncm/source/lr_contentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_contentlocationresolver.hpp @@ -34,6 +34,8 @@ namespace sts::lr { ContentLocationResolverInterface(ncm::StorageId storage_id) : storage_id(storage_id) { /* ... */ } ~ContentLocationResolverInterface(); + private: + void GetContentStoragePath(Path* out, ncm::ContentId content_id); public: virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) override; virtual Result RedirectProgramPath(InPointer path, ncm::TitleId tid) override; diff --git a/stratosphere/ncm/source/lr_ilocationresolver.hpp b/stratosphere/ncm/source/lr_ilocationresolver.hpp index fa669430f..5910b16b8 100644 --- a/stratosphere/ncm/source/lr_ilocationresolver.hpp +++ b/stratosphere/ncm/source/lr_ilocationresolver.hpp @@ -52,6 +52,18 @@ namespace sts::lr { impl::LocationRedirector app_control_redirector; impl::LocationRedirector html_docs_redirector; impl::LocationRedirector legal_info_redirector; + protected: + bool GetRedirectedPath(Path* out, impl::LocationRedirector* redirector, ncm::TitleId tid) { + return redirector->FindRedirection(out, tid); + } + + void ClearRedirections(u32 flags = impl::RedirectionFlags_None) { + this->program_redirector.ClearRedirections(flags); + this->debug_program_redirector.ClearRedirections(flags); + this->app_control_redirector.ClearRedirections(flags); + this->html_docs_redirector.ClearRedirections(flags); + this->legal_info_redirector.ClearRedirections(flags); + } public: virtual Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); virtual Result RedirectProgramPath(InPointer path, ncm::TitleId tid); diff --git a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp index 97f8592fd..c8c61a80d 100644 --- a/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp +++ b/stratosphere/ncm/source/lr_redirectonlylocationresolver.cpp @@ -28,7 +28,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->program_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->program_redirector, tid)) { return ResultSuccess; } @@ -41,7 +41,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationControlPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->app_control_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->app_control_redirector, tid)) { return ResultSuccess; } @@ -49,7 +49,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->html_docs_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->html_docs_redirector, tid)) { return ResultSuccess; } @@ -71,7 +71,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveApplicationLegalInformationPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->legal_info_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->legal_info_redirector, tid)) { return ResultSuccess; } @@ -127,7 +127,7 @@ namespace sts::lr { } Result RedirectOnlyLocationResolverInterface::ResolveProgramPathForDebug(OutPointerWithServerSize out, ncm::TitleId tid) { - if (this->debug_program_redirector.FindRedirection(out.pointer, tid)) { + if (this->GetRedirectedPath(out.pointer, &this->debug_program_redirector, tid)) { return ResultSuccess; } From 8bfc1c53941474b5340c1c0cbc39f33c38b4070f Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 16 Aug 2019 16:40:08 +1000 Subject: [PATCH 56/58] lr: RegisteredLocationResolver helpers --- .../source/lr_registeredlocationresolver.cpp | 55 ++++++++++--------- .../source/lr_registeredlocationresolver.hpp | 4 ++ 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 8e9f53efa..939cf3de6 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -20,28 +20,40 @@ namespace sts::lr { RegisteredLocationResolverInterface::~RegisteredLocationResolverInterface() { /* Ensure entries are deallocated */ + this->ClearRedirections(); + } + + void RegisteredLocationResolverInterface::ClearRedirections(u32 flags) { this->html_docs_redirector.ClearRedirections(); this->program_redirector.ClearRedirections(); } - Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (!this->program_redirector.FindRedirection(out.pointer, tid)) { - if (!this->registered_program_locations.Find(out.pointer, tid)) { - return ResultLrProgramNotFound; + void RegisteredLocationResolverInterface::RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid) { + if (!locations->Register(tid, path)) { + locations->Clear(); + locations->Register(tid, path); + } + } + + bool RegisteredLocationResolverInterface::ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid) { + if (!redirector->FindRedirection(out, tid)) { + if (!locations->Find(out, tid)) { + return false; } } - + return true; + } + + Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { + if (!this->ResolvePath(out.pointer, &this->program_redirector, &this->registered_program_locations, tid)) { + return ResultLrProgramNotFound; + } + return ResultSuccess; } Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - const Path& tmp_path = *path.pointer; - - if (!this->registered_program_locations.Register(tid, tmp_path)) { - this->registered_program_locations.Clear(); - this->registered_program_locations.Register(tid, tmp_path); - } - + this->RegisterPath(*path.pointer, &this->registered_program_locations, tid); return ResultSuccess; } @@ -56,23 +68,15 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { - if (!this->html_docs_redirector.FindRedirection(out.pointer, tid)) { - if (!this->registered_html_docs_locations.Find(out.pointer, tid)) { - return ResultLrProgramNotFound; - } + if (!this->ResolvePath(out.pointer, &this->html_docs_redirector, &this->registered_html_docs_locations, tid)) { + return ResultLrHtmlDocumentNotFound; } - return ResultLrHtmlDocumentNotFound; + return ResultSuccess; } Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - const Path& tmp_path = *path.pointer; - - if (!this->registered_html_docs_locations.Register(tid, tmp_path)) { - this->registered_html_docs_locations.Clear(); - this->registered_html_docs_locations.Register(tid, tmp_path); - } - + this->RegisterPath(*path.pointer, &this->registered_html_docs_locations, tid); return ResultSuccess; } @@ -87,8 +91,7 @@ namespace sts::lr { } Result RegisteredLocationResolverInterface::Refresh() { - this->registered_program_locations.Clear(); - this->registered_html_docs_locations.Clear(); + this->ClearRedirections(); return ResultSuccess; } diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index 0d6f0f4d7..f2e774c31 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -41,6 +41,10 @@ namespace sts::lr { impl::RegisteredLocations registered_program_locations; impl::LocationRedirector html_docs_redirector; impl::RegisteredLocations registered_html_docs_locations; + private: + void ClearRedirections(u32 flags = impl::RedirectionFlags_None); + void RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid); + bool ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid); public: ~RegisteredLocationResolverInterface(); From 4310a0018cc2fefa443e497a7cbc602abbaf2798 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Fri, 23 Aug 2019 15:05:19 +1000 Subject: [PATCH 57/58] ncm: Move ncm_types to libstrat --- .../include/stratosphere/ncm/ncm_types.hpp | 160 ++++++++++++++ .../include/stratosphere/util.hpp | 1 + .../include/stratosphere/util/util_uuid.hpp | 42 ++++ .../source/impl/ncm_placeholder_accessor.hpp | 1 - .../ncm/source/impl/ncm_rights_cache.hpp | 4 +- stratosphere/ncm/source/ncm_fs.hpp | 2 - .../ncm/source/ncm_icontentmetadatabase.hpp | 2 - .../ncm/source/ncm_icontentstorage.hpp | 2 - stratosphere/ncm/source/ncm_make_path.cpp | 8 +- stratosphere/ncm/source/ncm_make_path.hpp | 2 - stratosphere/ncm/source/ncm_path_utils.cpp | 2 +- stratosphere/ncm/source/ncm_path_utils.hpp | 2 - stratosphere/ncm/source/ncm_types.hpp | 201 ------------------ stratosphere/ncm/source/ncm_utils.hpp | 2 - 14 files changed, 209 insertions(+), 222 deletions(-) create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_uuid.hpp delete mode 100644 stratosphere/ncm/source/ncm_types.hpp diff --git a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp index 8edf4a833..29e6c366c 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp @@ -17,6 +17,7 @@ #pragma once #include +#include "../util/util_uuid.hpp" namespace sts::ncm { @@ -30,6 +31,104 @@ namespace sts::ncm { SdCard = 5, }; + enum class ContentMetaType : u8 { + Unknown = 0x0, + SystemProgram = 0x1, + SystemData = 0x2, + SystemUpdate = 0x3, + BootImagePackage = 0x4, + BootImagePackageSafe = 0x5, + Application = 0x80, + Patch = 0x81, + AddOnContent = 0x82, + Delta = 0x83, + }; + + enum class ContentType : u8 { + Meta = 0, + Program = 1, + Data = 2, + Control = 3, + HtmlDocument = 4, + LegalInformation = 5, + DeltaFragment = 6, + }; + + enum class ContentMetaAttribute : u8 { + None = 0, + IncludesExFatDriver = 1, + Rebootless = 2, + }; + + enum class ContentInstallType : u8 { + Full = 0, + FragmentOnly = 1, + Unknown = 7, + }; + + struct MountName { + char name[0x10]; + }; + + struct 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; + } + } __attribute__((aligned(8))); + + static_assert(__alignof__(PlaceHolderId) == 8, "PlaceHolderId definition!"); + + struct 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; + } + } __attribute__((aligned(4))); + + static_assert(__alignof__(ContentId) == 4, "ContentId definition!"); + + static constexpr PlaceHolderId InvalidPlaceHolderId = { util::InvalidUuid }; + static constexpr ContentId InvalidContentId = { util::InvalidUuid }; + + struct ContentInfo { + ContentId content_id; + u8 size[6]; + ContentType content_type; + u8 id_offset; + }; + + static_assert(sizeof(ContentInfo) == 0x18, "ContentInfo definition!"); + + typedef void (*MakeContentPathFunc)(char* out, ContentId content_id, const char* root); + typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); + /* Title IDs. */ struct TitleId { u64 value; @@ -429,4 +528,65 @@ namespace sts::ncm { static_assert(sizeof(TitleLocation) == 0x10 && std::is_pod::value, "TitleLocation definition!"); + struct ContentMetaKey { + TitleId id; + u32 version; + ContentMetaType type; + ContentInstallType install_type; + u8 padding[2]; + + bool operator<(const ContentMetaKey& other) const { + if (this->id < other.id) { + return true; + } else if (this->id != other.id) { + return false; + } + + if (this->version < other.version) { + return true; + } else if (this->version != other.version) { + return false; + } + + if (this->type < other.type) { + return true; + } else if (this->type != other.type) { + return false; + } + + return this->install_type < other.install_type; + } + + bool operator==(const ContentMetaKey& other) const { + return this->id == other.id && + this->version == other.version && + this->type == other.type && + this->install_type == other.install_type; + } + + bool operator!=(const ContentMetaKey& other) const { + return !(*this == other); + } + + static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type) { + return { .id = title_id, .version = version, .type = type }; + } + + static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type, ContentInstallType install_type) { + return { .id = title_id, .version = version, .type = type, .install_type = install_type }; + } + }; + + static_assert(sizeof(ContentMetaKey) == 0x10, "ContentMetaKey definition!"); + + /* Used by system updates. They share the exact same struct as ContentMetaKey */ + typedef ContentMetaKey ContentMetaInfo; + + struct ApplicationContentMetaKey { + ContentMetaKey key; + TitleId application_title_id; + }; + + static_assert(sizeof(ApplicationContentMetaKey) == 0x18, "ApplicationContentMetaKey definition!"); + } diff --git a/stratosphere/libstratosphere/include/stratosphere/util.hpp b/stratosphere/libstratosphere/include/stratosphere/util.hpp index d33453d60..a278887f3 100644 --- a/stratosphere/libstratosphere/include/stratosphere/util.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/util.hpp @@ -21,3 +21,4 @@ #include "util/util_ini.hpp" #include "util/util_intrusive_list.hpp" #include "util/util_intrusive_red_black_tree.hpp" +#include "util/util_uuid.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/util/util_uuid.hpp b/stratosphere/libstratosphere/include/stratosphere/util/util_uuid.hpp new file mode 100644 index 000000000..34f08eedb --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/util/util_uuid.hpp @@ -0,0 +1,42 @@ +/* + * 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 . + */ + +#pragma once +#include + +namespace sts::util { + + struct Uuid { + u8 uuid[0x10]; + + bool operator==(const Uuid& other) const { + return memcmp(this->uuid, other.uuid, sizeof(Uuid)) == 0; + } + + bool operator!=(const Uuid& other) const { + return !(*this == other); + } + + u8& operator[](size_t i) { + return uuid[i]; + } + }; + + static_assert(sizeof(Uuid) == 0x10, "Uuid definition!"); + + static constexpr Uuid InvalidUuid = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + +} \ No newline at end of file diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp index fd43a8b37..07baefa7e 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.hpp @@ -18,7 +18,6 @@ #include #include -#include "../ncm_types.hpp" #include "../ncm_path_utils.hpp" namespace sts::ncm::impl { diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp index 9750c2a13..1f1d74332 100644 --- a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp +++ b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp @@ -18,8 +18,6 @@ #include #include -#include "../ncm_types.hpp" - namespace sts::ncm::impl { class RightsIdCache { @@ -28,7 +26,7 @@ namespace sts::ncm::impl { public: struct Entry { public: - Uuid uuid; + util::Uuid uuid; FsRightsId rights_id; u64 key_generation; u64 last_accessed = 1; diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index 1194dbea9..e59b0417a 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -19,8 +19,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm { Result OpenFile(FILE** out, const char* path, u32 mode); diff --git a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp index 8eed6285c..194b4e541 100644 --- a/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp +++ b/stratosphere/ncm/source/ncm_icontentmetadatabase.hpp @@ -19,8 +19,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm { class IContentMetaDatabase : public IServiceObject { diff --git a/stratosphere/ncm/source/ncm_icontentstorage.hpp b/stratosphere/ncm/source/ncm_icontentstorage.hpp index 11b4a0661..01300b583 100644 --- a/stratosphere/ncm/source/ncm_icontentstorage.hpp +++ b/stratosphere/ncm/source/ncm_icontentstorage.hpp @@ -18,8 +18,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm { class IContentStorage : public IServiceObject { diff --git a/stratosphere/ncm/source/ncm_make_path.cpp b/stratosphere/ncm/source/ncm_make_path.cpp index d1e82b2cb..7ca9a7047 100644 --- a/stratosphere/ncm/source/ncm_make_path.cpp +++ b/stratosphere/ncm/source/ncm_make_path.cpp @@ -21,15 +21,15 @@ namespace sts::ncm::path { namespace { - u16 Get16BitSha256HashPrefix(Uuid uuid) { + u16 Get16BitSha256HashPrefix(util::Uuid uuid) { u8 hash[SHA256_HASH_SIZE]; - sha256CalculateHash(hash, uuid.uuid, sizeof(Uuid)); + sha256CalculateHash(hash, uuid.uuid, sizeof(util::Uuid)); return static_cast(hash[0]) | (static_cast(hash[1]) << 8); } - u8 Get8BitSha256HashPrefix(Uuid uuid) { + u8 Get8BitSha256HashPrefix(util::Uuid uuid) { u8 hash[SHA256_HASH_SIZE]; - sha256CalculateHash(hash, uuid.uuid, sizeof(Uuid)); + sha256CalculateHash(hash, uuid.uuid, sizeof(util::Uuid)); return hash[0]; } diff --git a/stratosphere/ncm/source/ncm_make_path.hpp b/stratosphere/ncm/source/ncm_make_path.hpp index b8cd03224..f71458815 100644 --- a/stratosphere/ncm/source/ncm_make_path.hpp +++ b/stratosphere/ncm/source/ncm_make_path.hpp @@ -18,8 +18,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm::path { void MakeContentPathFlat(char* out_path, ContentId content_id, const char* root); diff --git a/stratosphere/ncm/source/ncm_path_utils.cpp b/stratosphere/ncm/source/ncm_path_utils.cpp index cf51fcbd2..c0bb22481 100644 --- a/stratosphere/ncm/source/ncm_path_utils.cpp +++ b/stratosphere/ncm/source/ncm_path_utils.cpp @@ -66,7 +66,7 @@ namespace sts::ncm::path { return false; } - for (size_t i = 0; i < sizeof(Uuid)*2; i++) { + for (size_t i = 0; i < sizeof(util::Uuid)*2; i++) { if (!std::isxdigit(file_name.at(i))) { return false; } diff --git a/stratosphere/ncm/source/ncm_path_utils.hpp b/stratosphere/ncm/source/ncm_path_utils.hpp index e538a1aec..cf13e2fae 100644 --- a/stratosphere/ncm/source/ncm_path_utils.hpp +++ b/stratosphere/ncm/source/ncm_path_utils.hpp @@ -18,8 +18,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm::path { inline void GetContentRootPath(char* out_content_root, const char* root_path) { diff --git a/stratosphere/ncm/source/ncm_types.hpp b/stratosphere/ncm/source/ncm_types.hpp deleted file mode 100644 index 44e1192d2..000000000 --- a/stratosphere/ncm/source/ncm_types.hpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2019 Adubbz - * - * 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 . - */ - -#pragma once -#include -#include - -namespace sts::ncm { - - struct MountName { - char name[0x10]; - }; - - struct Uuid { - u8 uuid[0x10]; - - bool operator==(const Uuid& other) const { - return memcmp(this->uuid, other.uuid, sizeof(Uuid)) == 0; - } - - bool operator!=(const Uuid& other) const { - return !(*this == other); - } - - u8& operator[](size_t i) { - return uuid[i]; - } - }; - - static_assert(sizeof(Uuid) == 0x10, "Uuid definition!"); - - struct PlaceHolderId { - 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 Uuid& other) const { - return this->uuid == other; - } - - bool operator!=(const Uuid& other) const { - return this->uuid != other; - } - } __attribute__((aligned(8))); - - static_assert(__alignof__(PlaceHolderId) == 8, "PlaceHolderId definition!"); - - struct ContentId { - 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 Uuid& other) const { - return this->uuid == other; - } - - bool operator!=(const Uuid& other) const { - return this->uuid != other; - } - } __attribute__((aligned(4))); - - static_assert(__alignof__(ContentId) == 4, "ContentId definition!"); - - static constexpr Uuid InvalidUuid = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; - static constexpr PlaceHolderId InvalidPlaceHolderId = { InvalidUuid }; - static constexpr ContentId InvalidContentId = { InvalidUuid }; - - enum class ContentMetaType : u8 { - Unknown = 0x0, - SystemProgram = 0x1, - SystemData = 0x2, - SystemUpdate = 0x3, - BootImagePackage = 0x4, - BootImagePackageSafe = 0x5, - Application = 0x80, - Patch = 0x81, - AddOnContent = 0x82, - Delta = 0x83, - }; - - enum class ContentType : u8 { - Meta = 0, - Program = 1, - Data = 2, - Control = 3, - HtmlDocument = 4, - LegalInformation = 5, - DeltaFragment = 6, - }; - - enum class ContentMetaAttribute : u8 { - None = 0, - IncludesExFatDriver = 1, - Rebootless = 2, - }; - - enum class ContentInstallType : u8 { - Full = 0, - FragmentOnly = 1, - Unknown = 7, - }; - - struct ContentMetaKey { - TitleId id; - u32 version; - ContentMetaType type; - ContentInstallType install_type; - u8 padding[2]; - - bool operator<(const ContentMetaKey& other) const { - if (this->id < other.id) { - return true; - } else if (this->id != other.id) { - return false; - } - - if (this->version < other.version) { - return true; - } else if (this->version != other.version) { - return false; - } - - if (this->type < other.type) { - return true; - } else if (this->type != other.type) { - return false; - } - - return this->install_type < other.install_type; - } - - bool operator==(const ContentMetaKey& other) const { - return this->id == other.id && - this->version == other.version && - this->type == other.type && - this->install_type == other.install_type; - } - - bool operator!=(const ContentMetaKey& other) const { - return !(*this == other); - } - - static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type) { - return { .id = title_id, .version = version, .type = type }; - } - - static constexpr ContentMetaKey Make(TitleId title_id, u32 version, ContentMetaType type, ContentInstallType install_type) { - return { .id = title_id, .version = version, .type = type, .install_type = install_type }; - } - }; - - static_assert(sizeof(ContentMetaKey) == 0x10, "ContentMetaKey definition!"); - - // Used by system updates. They share the exact same struct as ContentMetaKey; - typedef ContentMetaKey ContentMetaInfo; - - struct ApplicationContentMetaKey { - ContentMetaKey key; - TitleId application_title_id; - }; - - static_assert(sizeof(ApplicationContentMetaKey) == 0x18, "ApplicationContentMetaKey definition!"); - - struct ContentInfo { - ContentId content_id; - u8 size[6]; - ContentType content_type; - u8 id_offset; - }; - - static_assert(sizeof(ContentInfo) == 0x18, "ContentInfo definition!"); - - typedef void (*MakeContentPathFunc)(char* out, ContentId content_id, const char* root); - typedef void (*MakePlaceHolderPathFunc)(char* out, PlaceHolderId placeholder_id, const char* root); - -} diff --git a/stratosphere/ncm/source/ncm_utils.hpp b/stratosphere/ncm/source/ncm_utils.hpp index 10aeb248a..920357a8b 100644 --- a/stratosphere/ncm/source/ncm_utils.hpp +++ b/stratosphere/ncm/source/ncm_utils.hpp @@ -19,8 +19,6 @@ #include #include -#include "ncm_types.hpp" - namespace sts::ncm { void GetStringFromContentId(char* out, ContentId content_id); From fec5432c4bc9d183172e03bf870e36080b320616 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 24 Aug 2019 16:02:08 +1000 Subject: [PATCH 58/58] ncm: Misc cleanup --- .../include/stratosphere/ncm/ncm_types.hpp | 3 + .../source/updater/updater_api.cpp | 6 +- .../ncm/source/impl/ncm_content_manager.cpp | 60 +++++++++---------- .../source/impl/ncm_placeholder_accessor.cpp | 6 +- .../ncm/source/ncm_contentmetadatabase.cpp | 14 ++--- .../ncm/source/ncm_contentstorage.cpp | 38 ++++++------ stratosphere/ncm/source/ncm_fs.cpp | 2 +- stratosphere/ncm/source/ncm_fs.hpp | 14 ++--- .../ncm/source/ncm_readonlycontentstorage.cpp | 20 +++---- 9 files changed, 83 insertions(+), 80 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp index 29e6c366c..a8b578321 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp @@ -17,10 +17,13 @@ #pragma once #include +#include "../lr/lr_types.hpp" #include "../util/util_uuid.hpp" namespace sts::ncm { + using Path = lr::Path; + /* Storage IDs. */ enum class StorageId : u8 { None = 0, diff --git a/stratosphere/libstratosphere/source/updater/updater_api.cpp b/stratosphere/libstratosphere/source/updater/updater_api.cpp index 2e6afd254..f027e5089 100644 --- a/stratosphere/libstratosphere/source/updater/updater_api.cpp +++ b/stratosphere/libstratosphere/source/updater/updater_api.cpp @@ -349,7 +349,7 @@ namespace sts::updater { void *work = reinterpret_cast(reinterpret_cast(work_buffer) + BctSize); size_t size; - R_TRY(ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); + R_TRY(fs::ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); if (HasEks(boot_image_update_type)) { R_TRY(boot0_accessor.UpdateEks(bct, work)); } @@ -411,7 +411,7 @@ namespace sts::updater { void *work = reinterpret_cast(reinterpret_cast(work_buffer) + BctSize); size_t size; - R_TRY(ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); + R_TRY(fs::ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); if (HasEks(boot_image_update_type)) { R_TRY(boot0_accessor.UpdateEks(bct, work)); } @@ -465,7 +465,7 @@ namespace sts::updater { void *work = reinterpret_cast(reinterpret_cast(work_buffer) + BctSize); size_t size; - R_TRY(ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); + R_TRY(fs::ReadFile(&size, bct, BctSize, GetBctPath(boot_image_update_type))); if (HasEks(boot_image_update_type)) { R_TRY(accessor.UpdateEks(bct, work)); } diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp index 28e1b80ee..01ec3f94e 100644 --- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp +++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp @@ -50,7 +50,7 @@ namespace sts::ncm::impl { this->storage_id = storage_id; this->content_storage_id = content_storage_id; this->content_storage = nullptr; - MountName mount_name = CreateUniqueMountName(); + MountName mount_name = fs::CreateUniqueMountName(); strcpy(this->mount_point, mount_name.name); snprintf(this->root_path, 0x80, "%s:/", this->mount_point); } @@ -90,7 +90,7 @@ namespace sts::ncm::impl { this->save_meta = save_meta; this->content_meta_database = nullptr; this->kvs.reset(); - MountName mount_name = CreateUniqueMountName(); + MountName mount_name = fs::CreateUniqueMountName(); strcpy(this->mount_point, mount_name.name); this->mount_point[0] = '#'; snprintf(this->meta_path, 0x80, "%s:/meta", this->mount_point); @@ -195,8 +195,8 @@ namespace sts::ncm::impl { } u32 current_flags = 0; - if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200 && R_SUCCEEDED(GetSaveDataFlags(¤t_flags, 0x8000000000000120)) && current_flags != (FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment)) { - SetSaveDataFlags(0x8000000000000120, FsSaveDataSpaceId_NandSystem, FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment); + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200 && R_SUCCEEDED(fs::GetSaveDataFlags(¤t_flags, 0x8000000000000120)) && current_flags != (FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment)) { + fs::SetSaveDataFlags(0x8000000000000120, FsSaveDataSpaceId_NandSystem, FsSaveDataFlags_SurviveFactoryReset | FsSaveDataFlags_SurviveFactoryResetForRefurbishment); } R_TRY(ActivateContentMetaDatabase(StorageId::NandSystem)); @@ -291,14 +291,14 @@ namespace sts::ncm::impl { return ResultNcmUnknownStorage; } - R_TRY(MountContentStorage(entry->mount_point, entry->content_storage_id)); + R_TRY(fs::MountContentStorage(entry->mount_point, entry->content_storage_id)); ON_SCOPE_EXIT { - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); }; - R_TRY(EnsureDirectoryRecursively(entry->root_path)); - R_TRY(EnsureContentAndPlaceHolderRoot(entry->root_path)); + R_TRY(fs::EnsureDirectoryRecursively(entry->root_path)); + R_TRY(fs::EnsureContentAndPlaceHolderRoot(entry->root_path)); return ResultSuccess; } @@ -316,17 +316,17 @@ namespace sts::ncm::impl { return ResultNcmUnknownStorage; } - MountName mount_name = CreateUniqueMountName(); + MountName mount_name = fs::CreateUniqueMountName(); char mount_root[128] = {0}; strcpy(mount_root, mount_name.name); strcat(mount_root, strchr(entry->root_path, ':')); - R_TRY(MountContentStorage(mount_name.name, entry->content_storage_id)); + R_TRY(fs::MountContentStorage(mount_name.name, entry->content_storage_id)); ON_SCOPE_EXIT { - Unmount(mount_name.name); + fs::Unmount(mount_name.name); }; - R_TRY(CheckContentStorageDirectoriesExist(mount_root)); + R_TRY(fs::CheckContentStorageDirectoriesExist(mount_root)); return ResultSuccess; } @@ -394,7 +394,7 @@ namespace sts::ncm::impl { /* N doesn't bother checking the result of this */ entry->content_storage->DisableForcibly(); - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); entry->content_storage = nullptr; return ResultSuccess; } @@ -419,17 +419,17 @@ namespace sts::ncm::impl { if (storage_id == StorageId::GameCard) { FsGameCardHandle gc_hnd; - R_TRY(GetGameCardHandle(&gc_hnd)); - R_TRY(MountGameCardPartition(entry->mount_point, gc_hnd, FsGameCardPartiton_Secure)); - auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + R_TRY(fs::GetGameCardHandle(&gc_hnd)); + R_TRY(fs::MountGameCardPartition(entry->mount_point, gc_hnd, FsGameCardPartiton_Secure)); + auto mount_guard = SCOPE_GUARD { fs::Unmount(entry->mount_point); }; auto content_storage = std::make_shared(); R_TRY(content_storage->Initialize(entry->root_path, path::MakeContentPathFlat)); entry->content_storage = std::move(content_storage); mount_guard.Cancel(); } else { - R_TRY(MountContentStorage(entry->mount_point, entry->content_storage_id)); - auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + R_TRY(fs::MountContentStorage(entry->mount_point, entry->content_storage_id)); + auto mount_guard = SCOPE_GUARD { fs::Unmount(entry->mount_point); }; MakeContentPathFunc content_path_func = nullptr; MakePlaceHolderPathFunc placeholder_path_func = nullptr; bool delay_flush = false; @@ -477,7 +477,7 @@ namespace sts::ncm::impl { entry->content_storage->DisableForcibly(); entry->content_storage = nullptr; - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); return ResultSuccess; } @@ -497,18 +497,18 @@ namespace sts::ncm::impl { /* N doesn't bother checking the result of this. */ fsDisableAutoSaveDataCreation(); - R_TRY_CATCH(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)) { + R_TRY_CATCH(fs::MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)) { R_CATCH(ResultFsTargetNotFound) { R_TRY(fsCreate_SystemSaveData(entry->save_meta.space_id, entry->save_meta.id, entry->save_meta.size, entry->save_meta.journal_size, entry->save_meta.flags)); - R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + R_TRY(fs::MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); } } R_END_TRY_CATCH; ON_SCOPE_EXIT { - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); }; - R_TRY(EnsureDirectoryRecursively(entry->meta_path)); + R_TRY(fs::EnsureDirectoryRecursively(entry->meta_path)); R_TRY(fsdevCommitDevice(entry->mount_point)); return ResultSuccess; @@ -534,18 +534,18 @@ namespace sts::ncm::impl { bool mounted_save_data = false; if (!entry->content_meta_database) { - R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + R_TRY(fs::MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); mounted_save_data = true; } ON_SCOPE_EXIT { if (mounted_save_data) { - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); } }; bool has_meta_path = false; - R_TRY(HasDirectory(&has_meta_path, entry->meta_path)); + R_TRY(fs::HasDirectory(&has_meta_path, entry->meta_path)); if (!has_meta_path) { return ResultNcmInvalidContentMetaDatabase; } @@ -620,7 +620,7 @@ namespace sts::ncm::impl { content_meta_db->DisableForcibly(); if (storage_id != StorageId::GameCard) { - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); } entry->content_meta_database = nullptr; @@ -663,8 +663,8 @@ namespace sts::ncm::impl { entry->kvs.emplace(); if (storage_id != StorageId::GameCard) { - R_TRY(MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); - auto mount_guard = SCOPE_GUARD { Unmount(entry->mount_point); }; + R_TRY(fs::MountSystemSaveData(entry->mount_point, entry->save_meta.space_id, entry->save_meta.id)); + auto mount_guard = SCOPE_GUARD { fs::Unmount(entry->mount_point); }; R_TRY(entry->kvs->Initialize(entry->meta_path, entry->max_content_metas)); R_TRY(entry->kvs->Load()); @@ -701,7 +701,7 @@ namespace sts::ncm::impl { entry->kvs.reset(); if (storage_id != StorageId::GameCard) { - Unmount(entry->mount_point); + fs::Unmount(entry->mount_point); } return ResultSuccess; diff --git a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp index ae367f2e6..cde68810c 100644 --- a/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp +++ b/stratosphere/ncm/source/impl/ncm_placeholder_accessor.cpp @@ -30,7 +30,7 @@ namespace sts::ncm::impl { this->MakePath(placeholder_path, placeholder_id); FILE* f = nullptr; - R_TRY(OpenFile(&f, placeholder_path, FS_OPEN_WRITE)); + R_TRY(fs::OpenFile(&f, placeholder_path, FS_OPEN_WRITE)); *out_handle = f; return ResultSuccess; @@ -164,7 +164,7 @@ namespace sts::ncm::impl { this->StoreToCache(f, placeholder_id); }; - R_TRY(WriteFile(f, offset, buffer, size, !this->delay_flush)); + R_TRY(fs::WriteFile(f, offset, buffer, size, !this->delay_flush)); return ResultSuccess; } @@ -223,7 +223,7 @@ namespace sts::ncm::impl { Result PlaceHolderAccessor::EnsureRecursively(PlaceHolderId placeholder_id) { char placeholder_path[FS_MAX_PATH] = {0}; this->MakePath(placeholder_path, placeholder_id); - R_TRY(EnsureParentDirectoryRecursively(placeholder_path)); + R_TRY(fs::EnsureParentDirectoryRecursively(placeholder_path)); return ResultSuccess; } diff --git a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp index 6900a1404..885e1c848 100644 --- a/stratosphere/ncm/source/ncm_contentmetadatabase.cpp +++ b/stratosphere/ncm/source/ncm_contentmetadatabase.cpp @@ -21,15 +21,15 @@ namespace sts::ncm { namespace { - struct InstallContentMetaHeader { + struct ContentMetaHeader { u16 extended_header_size; u16 content_count; u16 content_meta_count; ContentMetaAttribute attributes; - u8 padding; + StorageId storage_id; }; - static_assert(sizeof(InstallContentMetaHeader) == 0x8, "InstallContentMetaHeader definition!"); + static_assert(sizeof(ContentMetaHeader) == 0x8, "ContentMetaHeader definition!"); struct ApplicationMetaExtendedHeader { TitleId patch_id; @@ -54,17 +54,17 @@ namespace sts::ncm { u32 extended_data_size; }; - inline const InstallContentMetaHeader* GetValueHeader(const void* value) { - return reinterpret_cast(value); + inline const ContentMetaHeader* GetValueHeader(const void* value) { + return reinterpret_cast(value); } template inline const ExtendedHeaderType* GetValueExtendedHeader(const void* value) { - return reinterpret_cast(reinterpret_cast(value) + sizeof(InstallContentMetaHeader)); + return reinterpret_cast(reinterpret_cast(value) + sizeof(ContentMetaHeader)); } inline const ContentInfo* GetValueContentInfos(const void* value) { - return reinterpret_cast(reinterpret_cast(value) + sizeof(InstallContentMetaHeader) + GetValueHeader(value)->extended_header_size); + return reinterpret_cast(reinterpret_cast(value) + sizeof(ContentMetaHeader) + GetValueHeader(value)->extended_header_size); } inline const ContentMetaInfo* GetValueContentMetaInfos(const void* value) { diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp index d57ab3e5e..01f177124 100644 --- a/stratosphere/ncm/source/ncm_contentstorage.cpp +++ b/stratosphere/ncm/source/ncm_contentstorage.cpp @@ -28,7 +28,7 @@ namespace sts::ncm { Result ContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush) { R_TRY(this->EnsureEnabled()); - R_TRY(CheckContentStorageDirectoriesExist(root_path)); + R_TRY(fs::CheckContentStorageDirectoriesExist(root_path)); const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1); if (root_path_len >= FS_MAX_PATH-1) { @@ -76,7 +76,7 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - R_TRY_CATCH(OpenFile(&this->content_cache_file_handle, content_path, FS_OPEN_READ)) { + R_TRY_CATCH(fs::OpenFile(&this->content_cache_file_handle, content_path, FS_OPEN_READ)) { R_CATCH(ResultFsPathNotFound) { return ResultNcmContentNotFound; } @@ -101,7 +101,7 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - R_TRY(EnsureParentDirectoryRecursively(content_path)); + R_TRY(fs::EnsureParentDirectoryRecursively(content_path)); R_TRY(this->placeholder_accessor.Create(placeholder_id, size)); return ResultSuccess; @@ -119,7 +119,7 @@ namespace sts::ncm { this->placeholder_accessor.MakePath(placeholder_path, placeholder_id); bool has = false; - R_TRY(HasFile(&has, placeholder_path)); + R_TRY(fs::HasFile(&has, placeholder_path)); out.SetValue(has); return ResultSuccess; @@ -185,7 +185,7 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); bool has = false; - R_TRY(HasFile(&has, content_path)); + R_TRY(fs::HasFile(&has, content_path)); out.SetValue(has); return ResultSuccess; @@ -197,7 +197,7 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; return ResultSuccess; } @@ -208,7 +208,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); *out.pointer = common_path; return ResultSuccess; } @@ -239,7 +239,7 @@ namespace sts::ncm { const unsigned int dir_depth = this->placeholder_accessor.GetDirectoryDepth(); size_t entry_count = 0; - R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + R_TRY(fs::TraverseDirectory(placeholder_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { *should_continue = true; *should_retry_dir_read = false; @@ -268,7 +268,7 @@ namespace sts::ncm { const unsigned int dir_depth = this->GetContentDirectoryDepth(); u32 content_count = 0; - R_TRY(TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + R_TRY(fs::TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { *should_continue = true; *should_retry_dir_read = false; @@ -295,7 +295,7 @@ namespace sts::ncm { const unsigned int dir_depth = this->GetContentDirectoryDepth(); size_t entry_count = 0; - R_TRY(TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { + R_TRY(fs::TraverseDirectory(content_root_path, dir_depth, [&](bool* should_continue, bool* should_retry_dir_read, const char* current_path, struct dirent* dir_entry) { *should_retry_dir_read = false; *should_continue = true; @@ -368,7 +368,7 @@ namespace sts::ncm { /* Ensure the new content path is ready. */ this->GetContentPath(new_content_path, new_content_id); - R_TRY(EnsureParentDirectoryRecursively(new_content_path)); + R_TRY(fs::EnsureParentDirectoryRecursively(new_content_path)); R_TRY(this->placeholder_accessor.EnsureRecursively(placeholder_id)); this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); @@ -402,7 +402,7 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); R_TRY(this->OpenCachedContentFile(content_id)); - R_TRY(ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); + R_TRY(fs::ReadFile(this->content_cache_file_handle, offset, buf.buffer, buf.num_elements)); return ResultSuccess; } @@ -416,7 +416,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); out_rights_id.SetValue(rights_id); @@ -452,7 +452,7 @@ namespace sts::ncm { char content_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->GetContentPath(content_path, content_id); - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); { @@ -504,13 +504,13 @@ namespace sts::ncm { this->GetContentPath(content_path, content_id); FILE* f = nullptr; - R_TRY(OpenFile(&f, content_path, FS_OPEN_WRITE)); + R_TRY(fs::OpenFile(&f, content_path, FS_OPEN_WRITE)); ON_SCOPE_EXIT { fclose(f); }; - R_TRY(WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); + R_TRY(fs::WriteFile(f, offset, data.buffer, data.num_elements, FS_WRITEOPTION_FLUSH)); return ResultSuccess; } @@ -584,14 +584,14 @@ namespace sts::ncm { return ResultSuccess; }; - R_TRY(TraverseDirectory(content_root_path, dir_depth, fix_file_attributes)); + R_TRY(fs::TraverseDirectory(content_root_path, dir_depth, fix_file_attributes)); char placeholder_root_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.InvalidateAll(); this->placeholder_accessor.MakeRootPath(placeholder_root_path); dir_depth = this->placeholder_accessor.GetDirectoryDepth(); - R_TRY(TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); + R_TRY(fs::TraverseDirectory(placeholder_root_path, dir_depth, fix_file_attributes)); return ResultSuccess; } @@ -623,7 +623,7 @@ namespace sts::ncm { char placeholder_path[FS_MAX_PATH] = {0}; char common_path[FS_MAX_PATH] = {0}; this->placeholder_accessor.GetPath(placeholder_path, placeholder_id); - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, placeholder_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); { diff --git a/stratosphere/ncm/source/ncm_fs.cpp b/stratosphere/ncm/source/ncm_fs.cpp index 4773c3b0a..abecb6647 100644 --- a/stratosphere/ncm/source/ncm_fs.cpp +++ b/stratosphere/ncm/source/ncm_fs.cpp @@ -21,7 +21,7 @@ #include "ncm_fs.hpp" #include "ncm_path_utils.hpp" -namespace sts::ncm { +namespace sts::ncm::fs { Result OpenFile(FILE** out, const char* path, u32 mode) { bool has = false; diff --git a/stratosphere/ncm/source/ncm_fs.hpp b/stratosphere/ncm/source/ncm_fs.hpp index e59b0417a..9ff613c9c 100644 --- a/stratosphere/ncm/source/ncm_fs.hpp +++ b/stratosphere/ncm/source/ncm_fs.hpp @@ -19,7 +19,7 @@ #include #include -namespace sts::ncm { +namespace sts::ncm::fs { Result OpenFile(FILE** out, const char* path, u32 mode); Result WriteFile(FILE* f, size_t offset, const void* buffer, size_t size, u32 option); @@ -50,12 +50,6 @@ namespace sts::ncm { Result GetSaveDataFlags(u32* out_flags, u64 save_id); Result SetSaveDataFlags(u64 save_id, FsSaveDataSpaceId space_id, u32 flags); - template - Result TraverseDirectory(const char* root_path, int max_level, F f) { - bool should_continue = false; - return TraverseDirectory(&should_continue, root_path, max_level, f); - } - template Result TraverseDirectory(bool* out_should_continue, const char* root_path, int max_level, F f) { DIR *dir; @@ -111,4 +105,10 @@ namespace sts::ncm { return ResultSuccess; }; + template + Result TraverseDirectory(const char* root_path, int max_level, F f) { + bool should_continue = false; + return TraverseDirectory(&should_continue, root_path, max_level, f); + } + } diff --git a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp index 0fb32eb5f..204a68f9e 100644 --- a/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp +++ b/stratosphere/ncm/source/ncm_readonlycontentstorage.cpp @@ -69,11 +69,11 @@ namespace sts::ncm { this->make_content_path_func(content_path, content_id, this->root_path); bool has = false; - R_TRY(HasFile(&has, content_path)); + R_TRY(fs::HasFile(&has, content_path)); if (!has) { path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); - R_TRY(HasFile(&has, content_path)); + R_TRY(fs::HasFile(&has, content_path)); } out.SetValue(has); @@ -88,13 +88,13 @@ namespace sts::ncm { bool is_content_meta_file = false; path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); - R_TRY(HasFile(&is_content_meta_file, content_path)); + R_TRY(fs::HasFile(&is_content_meta_file, content_path)); if (!is_content_meta_file) { this->make_content_path_func(content_path, content_id, this->root_path); } - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); *out.pointer = common_path; return ResultSuccess; @@ -127,7 +127,7 @@ namespace sts::ncm { bool is_content_file = false; this->make_content_path_func(content_path, content_id, this->root_path); - R_TRY(HasFile(&is_content_file, content_path)); + R_TRY(fs::HasFile(&is_content_file, content_path)); if (!is_content_file) { path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); @@ -167,20 +167,20 @@ namespace sts::ncm { bool is_content_file = false; this->make_content_path_func(content_path, content_id, this->root_path); - R_TRY(HasFile(&is_content_file, content_path)); + R_TRY(fs::HasFile(&is_content_file, content_path)); if (!is_content_file) { path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); } FILE* f = nullptr; - R_TRY(OpenFile(&f, content_path, FS_OPEN_READ)); + R_TRY(fs::OpenFile(&f, content_path, FS_OPEN_READ)); ON_SCOPE_EXIT { fclose(f); }; - R_TRY(ReadFile(f, offset, buf.buffer, buf.num_elements)); + R_TRY(fs::ReadFile(f, offset, buf.buffer, buf.num_elements)); return ResultSuccess; } @@ -200,13 +200,13 @@ namespace sts::ncm { bool is_content_meta_file = false; path::GetContentMetaPath(content_path, content_id, this->make_content_path_func, this->root_path); - R_TRY(HasFile(&is_content_meta_file, content_path)); + R_TRY(fs::HasFile(&is_content_meta_file, content_path)); if (!is_content_meta_file) { this->make_content_path_func(content_path, content_id, this->root_path); } - R_TRY(ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); + R_TRY(fs::ConvertToFsCommonPath(common_path, FS_MAX_PATH-1, content_path)); R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id)); out_rights_id.SetValue(rights_id);