ams: support building unit test programs on windows/linux/macos

This commit is contained in:
Michael Scire 2022-03-06 12:08:20 -08:00
parent c5ae3c2449
commit d7a9c7ec4c
648 changed files with 26708 additions and 5542 deletions

View File

@ -1,10 +0,0 @@
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere libexosphere
TOPTARGETS := all clean
$(TOPTARGETS): $(ATMOSPHERE_LIBRARIES)
$(ATMOSPHERE_LIBRARIES):
$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(TOPTARGETS) $(ATMOSPHERE_LIBRARIES)

View File

@ -1,11 +1,23 @@
ifeq ($(strip $(ATMOSPHERE_OS_NAME)),horizon)
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
include $(DEVKITPRO)/devkitA64/base_rules
else
include $(ATMOSPHERE_ARCH_MAKE_DIR)/base_rules
endif
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
export ATMOSPHERE_SETTINGS += -mtp=soft
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=
ifeq ($(strip $(ATMOSPHERE_OS_NAME)),horizon)
export ATMOSPHERE_SETTINGS += -mtp=soft
endif

View File

@ -0,0 +1,28 @@
include $(ATMOSPHERE_ARCH_MAKE_DIR)/base_tools
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
$(SILENTMSG) $(notdir $@)
@rm -f $@
$(SILENTCMD)$(AR) -rc $@ $^
#---------------------------------------------------------------------------------
%.o: %.cpp
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.c
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.s
@echo $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.S
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)

View File

@ -0,0 +1,52 @@
#---------------------------------------------------------------------------------
# the prefix on the compiler executables
#---------------------------------------------------------------------------------
PREFIX :=
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),gcc)
export CC := gcc
export CXX := g++
export AS := as
export AR := gcc-ar
export OBJCOPY := objcopy
export STRIP := strip
export NM := gcc-nm
export RANLIB := gcc-ranlib
else ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export CC := clang
export CXX := clang++
export AS := llvm-as
export AR := llvm-ar
export OBJCOPY := llvm-objcopy
export STRIP := llvm-strip
export NM := llvm-nm
export RANLIB := llvm-ranlib
endif
ISVC=$(or $(VCBUILDHELPER_COMMAND),$(MSBUILDEXTENSIONSPATH32),$(MSBUILDEXTENSIONSPATH))
ifneq (,$(ISVC))
ERROR_FILTER := 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/g'
endif
#---------------------------------------------------------------------------------
# allow seeing compiler command lines with make V=1 (similar to autotools' silent)
#---------------------------------------------------------------------------------
ifeq ($(V),1)
SILENTMSG := @true
SILENTCMD :=
else
SILENTMSG := @echo
SILENTCMD := @
endif
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
define bin2o
bin2s -a 8 -H `(echo $(<F) | tr . _)`.h $< | $(AS) -o $(<F).o
endef

View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_GENERIC_ARM64
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mno-outline-atomics
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

7
config/arch/x64/arch.mk Normal file
View File

@ -0,0 +1,7 @@
include $(ATMOSPHERE_ARCH_MAKE_DIR)/base_rules
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_X64
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -0,0 +1,28 @@
include $(ATMOSPHERE_ARCH_MAKE_DIR)/base_tools
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
$(SILENTMSG) $(notdir $@)
@rm -f $@
$(SILENTCMD)$(AR) -rc $@ $^
#---------------------------------------------------------------------------------
%.o: %.cpp
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.c
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.s
@echo $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.S
$(SILENTMSG) $(notdir $<)
$(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)

View File

@ -0,0 +1,52 @@
#---------------------------------------------------------------------------------
# the prefix on the compiler executables
#---------------------------------------------------------------------------------
PREFIX :=
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),gcc)
export CC := gcc
export CXX := g++
export AS := as
export AR := gcc-ar
export OBJCOPY := objcopy
export STRIP := strip
export NM := gcc-nm
export RANLIB := gcc-ranlib
else ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export CC := clang
export CXX := clang++
export AS := llvm-as
export AR := llvm-ar
export OBJCOPY := llvm-objcopy
export STRIP := llvm-strip
export NM := llvm-nm
export RANLIB := llvm-ranlib
endif
ISVC=$(or $(VCBUILDHELPER_COMMAND),$(MSBUILDEXTENSIONSPATH32),$(MSBUILDEXTENSIONSPATH))
ifneq (,$(ISVC))
ERROR_FILTER := 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/g'
endif
#---------------------------------------------------------------------------------
# allow seeing compiler command lines with make V=1 (similar to autotools' silent)
#---------------------------------------------------------------------------------
ifeq ($(V),1)
SILENTMSG := @true
SILENTCMD :=
else
SILENTMSG := @echo
SILENTCMD := @
endif
#---------------------------------------------------------------------------------
# canned command sequence for binary data
#---------------------------------------------------------------------------------
define bin2o
bin2s -a 8 -H `(echo $(<F) | tr . _)`.h $< | $(AS) -o $(<F).o
endef

View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_GENERIC_X64
export ATMOSPHERE_SETTINGS += -march=native -mtune=generic
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -0,0 +1,19 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_GENERIC_LINUX
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export ATMOSPHERE_CXXFLAGS += -stdlib=libc++
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),x64)
export ATMOSPHERE_SETTINGS += -target x86_64-pc-linux-gnu
else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
export ATMOSPHERE_SETTINGS += -target aarch64-linux-gnu
endif
endif
# TODO: Better way of doing this?
export ATMOSPHERE_CXXFLAGS += -I/opt/libjpeg-turbo/include

View File

@ -0,0 +1,23 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_GENERIC_MACOS
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export ATMOSPHERE_CXXFLAGS += -stdlib=libc++
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),x64)
export ATMOSPHERE_SETTINGS += -target x86_64-apple-darwin
else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
export ATMOSPHERE_SETTINGS += -target aarch64-apple-darwin
endif
endif
ifeq ($(strip $(SDKROOT)),)
export SDKROOT := $(shell xcrun --sdk macosx --show-sdk-path)
endif
# TODO: Better way of doing this?
export ATMOSPHERE_CXXFLAGS += -I/opt/libjpeg-turbo/include

View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_GENERIC_WINDOWS
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -15,14 +15,34 @@ endif
endif
ifeq ($(ATMOSPHERE_BUILD_NAME),)
export ATMOSPHERE_BUILD_NAME := release
endif
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),)
ifneq ($(strip $(ATMOSPHERE_BOARD)),generic_macos)
export ATMOSPHERE_COMPILER_NAME := gcc
else
export ATMOSPHERE_COMPILER_NAME := clang
endif
export ATMOSPHERE_BUILD_NAME := release
endif
ATMOSPHERE_BUILD_SETTINGS ?=
export ATMOSPHERE_DEFINES := -DATMOSPHERE
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
-Wno-format-zero-length
ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),gcc)
export ATMOSPHERE_CFLAGS += -Wno-stringop-truncation -Wno-format-truncation
else ifeq ($(strip $(ATMOSPHERE_COMPILER_NAME)),clang)
export ATMOSPHERE_CFLAGS += -Wno-c99-designator -Wno-gnu-alignof-expression -Wno-unused-private-field
endif
export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20 -Wno-invalid-offsetof
export ATMOSPHERE_ASFLAGS :=
@ -39,10 +59,16 @@ export ATMOSPHERE_ARCH_NAME := arm64
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_SUB_ARCH_DIR = armv8a
export ATMOSPHERE_SUB_ARCH_NAME = armv8a
export ATMOSPHERE_SUB_ARCH_DIR := armv8a
export ATMOSPHERE_SUB_ARCH_NAME := armv8a
export ATMOSPHERE_CPU_EXTENSIONS := arm_crypto_extension aarch64_crypto_extension
export ATMOSPHERE_BOOT_CPU := arm7tdmi
export ATMOSPHERE_BOOT_ARCH_NAME := arm
export ATMOSPHERE_BOOT_BOARD_NAME := nintendo_nx
export ATMOSPHERE_BOOT_OS_NAME := horizon
export ATMOSPHERE_BOOT_SUB_ARCH_NAME := armv4t
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_ARCH_DIR := arm
export ATMOSPHERE_BOARD_DIR := nintendo/nx_bpmp
@ -52,12 +78,14 @@ export ATMOSPHERE_ARCH_NAME := arm
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_SUB_ARCH_DIR = armv4t
export ATMOSPHERE_SUB_ARCH_NAME = armv4t
export ATMOSPHERE_SUB_ARCH_DIR := armv4t
export ATMOSPHERE_SUB_ARCH_NAME := armv4t
export ATMOSPHERE_CPU_EXTENSIONS :=
endif
export ATMOSPHERE_LIBDIRS :=
else ifeq ($(ATMOSPHERE_BOARD),qemu-virt)
@ -76,6 +104,53 @@ export ATMOSPHERE_SUB_ARCH_NAME = armv8a
export ATMOSPHERE_CPU_EXTENSIONS := arm_crypto_extension aarch64_crypto_extension
endif
export ATMOSPHERE_LIBDIRS :=
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
ifeq ($(ATMOSPHERE_CPU),generic_x64)
export ATMOSPHERE_ARCH_DIR := x64
export ATMOSPHERE_BOARD_DIR := generic/windows
export ATMOSPHERE_OS_DIR := windows
export ATMOSPHERE_ARCH_NAME := x64
export ATMOSPHERE_BOARD_NAME := generic_windows
export ATMOSPHERE_OS_NAME := windows
endif
else ifeq ($(ATMOSPHERE_BOARD),generic_linux)
ifeq ($(ATMOSPHERE_CPU),generic_x64)
export ATMOSPHERE_ARCH_DIR := x64
export ATMOSPHERE_ARCH_NAME := x64
else ifeq ($(ATMOSPHERE_CPU),generic_arm64)
export ATMOSPHERE_ARCH_DIR := arm64
export ATMOSPHERE_ARCH_NAME := arm64
endif
export ATMOSPHERE_BOARD_DIR := generic/linux
export ATMOSPHERE_OS_DIR := linux
export ATMOSPHERE_BOARD_NAME := generic_linux
export ATMOSPHERE_OS_NAME := linux
else ifeq ($(ATMOSPHERE_BOARD),generic_macos)
ifeq ($(ATMOSPHERE_CPU),generic_x64)
export ATMOSPHERE_ARCH_DIR := x64
export ATMOSPHERE_ARCH_NAME := x64
else ifeq ($(ATMOSPHERE_CPU),generic_arm64)
export ATMOSPHERE_ARCH_DIR := arm64
export ATMOSPHERE_ARCH_NAME := arm64
endif
export ATMOSPHERE_BOARD_DIR := generic/macos
export ATMOSPHERE_OS_DIR := macos
export ATMOSPHERE_BOARD_NAME := generic_macos
export ATMOSPHERE_OS_NAME := macos
endif
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
@ -88,6 +163,15 @@ export ATMOSPHERE_CPU_DIR := arm7tdmi
export ATMOSPHERE_CPU_NAME := arm7tdmi
endif
ifeq ($(ATMOSPHERE_CPU),generic_x64)
export ATMOSPHERE_CPU_DIR := generic_x64
export ATMOSPHERE_CPU_NAME := generic_x64
endif
ifeq ($(ATMOSPHERE_CPU),generic_arm64)
export ATMOSPHERE_CPU_DIR := generic_arm64
export ATMOSPHERE_CPU_NAME := generic_arm64
endif
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/arch/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/board/$(ATMOSPHERE_BOARD_DIR)
@ -95,11 +179,40 @@ export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/os/$(ATMOSPHER
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_ARCH_MAKE_DIR)/cpu/$(ATMOSPHERE_CPU_DIR)
ifneq ($(strip $(ATMOSPHERE_SUB_ARCH_NAME)),)
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)
export ATMOSPHERE_FULL_NAME := $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)_$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_LIBRARY_DIR := lib/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BUILD_DIR := build/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_OUT_DIR := out/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
else
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
export ATMOSPHERE_FULL_NAME := $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_LIBRARY_DIR := lib/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BUILD_DIR := build/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_OUT_DIR := out/$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
endif
ifneq ($(strip $(ATMOSPHERE_BOOT_ARCH_NAME)),)
ifneq ($(strip $(ATMOSPHERE_SUB_ARCH_NAME)),)
export ATMOSPHERE_BOOT_FULL_NAME := $(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)_$(ATMOSPHERE_BOOT_SUB_ARCH_NAME)_$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_LIBRARY_DIR := lib/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)_$(ATMOSPHERE_BOOT_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_BUILD_DIR := build/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)_$(ATMOSPHERE_BOOT_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_OUT_DIR := out/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)_$(ATMOSPHERE_BOOT_SUB_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
else
export ATMOSPHERE_BOOT_FULL_NAME := $(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)_$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_LIBRARY_DIR := lib/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_BUILD_DIR := build/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
export ATMOSPHERE_BOOT_OUT_DIR := out/$(ATMOSPHERE_BOOT_BOARD_NAME)_$(ATMOSPHERE_BOOT_ARCH_NAME)/$(ATMOSPHERE_BUILD_NAME)
endif
else
export ATMOSPHERE_BOOT_FULL_NAME := $(ATMOSPHERE_FULL_NAME)
export ATMOSPHERE_BOOT_LIBRARY_DIR := $(ATMOSPHERE_LIBRARY_DIR)
export ATMOSPHERE_BOOT_BUILD_DIR := $(ATMOSPHERE_BUILD_DIR)
export ATMOSPHERE_BOOT_OUT_DIR := $(ATMOSPHERE_OUT_DIR)
endif
ifeq ($(strip $(ATMOSPHERE_BOOT_CPU)),)
export ATMOSPHERE_BOOT_CPU := $(ATMOSPHERE_CPU)
endif
include $(ATMOSPHERE_ARCH_MAKE_DIR)/arch.mk
@ -182,15 +295,14 @@ FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arc
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
ATMOSPHERE_GCH_IDENTIFIER := $(ATMOSPHERE_FULL_NAME)
#---------------------------------------------------------------------------------
# Rules for compiling pre-compiled headers
#---------------------------------------------------------------------------------
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp %.hpp.gch
@echo Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
%.hpp.gch: %.hpp
@echo Precompiling $(notdir $<)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
@[ -d $@ ] || mkdir -p $@

5
config/os/linux/os.mk Normal file
View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_LINUX
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

5
config/os/macos/os.mk Normal file
View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_MACOS
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

5
config/os/windows/os.mk Normal file
View File

@ -0,0 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
export ATMOSPHERE_SETTINGS +=
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@ -7,8 +7,14 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
# options for code generation
#---------------------------------------------------------------------------------
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions \
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
endif
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE -DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -fno-non-call-exceptions \
-Wno-array-bounds \
-Wno-stringop-overflow \
-Wno-stringop-overread
@ -16,8 +22,14 @@ CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -Werror -fno-non-call-exceptions \
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -O2
endif
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE -DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS
SETTINGS := $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Werror -fno-non-call-exceptions \
-Wno-array-bounds \
-Wno-stringop-overflow \
-Wno-stringop-overread
@ -26,7 +38,7 @@ CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
endif
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -fno-rtti -fno-use-cxa-atexit -nostdlib -nostartfiles -g $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export LDFLAGS = -specs=$(ATMOSPHERE_TOPDIR)/$(notdir $(ATMOSPHERE_TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -fno-rtti -fno-use-cxa-atexit -nostdlib -nostartfiles -g $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,__cxa_throw \
@ -43,7 +55,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LIBS := -l$(LIBEXOSPHERE_NAME) -lgcc
export LIBS := -lexosphere -lgcc
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@ -6,13 +6,19 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
endif
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
export SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
export SETTINGS := $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export LDFLAGS = -specs=$(ATMOSPHERE_TOPDIR)/$(notdir $(ATMOSPHERE_TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,__cxa_throw \
@ -29,7 +35,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LIBS := -l$(LIBMESOSPHERE_NAME)
export LIBS := -lmesosphere
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@ -3,6 +3,8 @@
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
#---------------------------------------------------------------------------------
# pull in switch rules
#---------------------------------------------------------------------------------
@ -12,15 +14,24 @@ endif
include $(DEVKITPRO)/libnx/switch_rules
endif
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -O2
endif
export DEFINES = $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
export SETTINGS = $(ATMOSPHERE_SETTINGS) -O2 -Wextra -Werror -Wno-missing-field-initializers
export SETTINGS = $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -Wno-missing-field-initializers
export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
export ASFLAGS = $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export CXXREQUIRED := -Wl,--require-defined,__libnx_initheap \
-Wl,--require-defined,__libnx_exception_handler \
-Wl,--require-defined,__libnx_alloc \
@ -45,16 +56,50 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc \
-Wl,--wrap,exit
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
export CXXREQUIRED :=
export CXXWRAPS := -Wl,--wrap,__p__acmdln
else
export CXXREQUIRED :=
export CXXWRAPS :=
endif
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map)
else ifeq ($(ATMOSPHERE_BOARD),generic_macos)
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-map,$(notdir $@.map)
else
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map)
endif
export LIBS = -lstratosphere -lnx
ifeq ($(ATMOSPHERE_COMPILER_NAME),clang)
export LDFLAGS += -fuse-ld=lld
endif
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export LIBS := -lstratosphere -lnx
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
export LIBS := -lstratosphere -lwinmm -lws2_32
else ifeq ($(ATMOSPHERE_BOARD),generic_linux)
export LIBS := -lstratosphere -pthread
else ifeq ($(ATMOSPHERE_BOARD),generic_macos)
export LIBS := -lstratosphere -pthread
else
export LIBS := -lstratosphere
endif
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
export LIBDIRS = $(PORTLIBS) $(LIBNX) $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export LIBDIRS = $(PORTLIBS) $(LIBNX)
else
export LIBDIRS =
endif
export AMS_LIBDIRS = $(ATMOSPHERE_LIBRARIES_DIR)/libvapours $(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere
#---------------------------------------------------------------------------------
# stratosphere sysmodules may (but usually do not) have an exefs source dir

View File

@ -1,34 +1,42 @@
ATMOSPHERE_BUILD_CONFIGS :=
all: arm64-release arm-release
all: nx_release
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
arm64-$(strip $1):
@$$(MAKE) -f arm64.mk $(strip $1)
$(strip $1):
@echo "Building $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libexosphere.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
arm-$(strip $1):
@$$(MAKE) -f arm.mk $(strip $1)
clean-arm64-$(strip $1):
@$$(MAKE) -f arm64.mk clean-$(strip $1)
clean-arm-$(strip $1):
@$$(MAKE) -f arm.mk clean-$(strip $1)
clean-$(strip $1):
@echo "Cleaning $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libexosphere.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit))
define ATMOSPHERE_ADD_TARGETS
clean-arm64:
@$(MAKE) -f arm64.mk clean
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_release, release, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4)" \
))
clean-arm:
@$(MAKE) -f arm.mk clean
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_debug, debug, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_DEBUGGING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 \
))
clean: clean-arm64 clean-arm
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_audit, audit, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_AUDITING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 ATMOSPHERE_BUILD_FOR_AUDITING=1 \
))
.PHONY: all clean clean-arm64 clean-arm $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),arm64-$(config) arm-$(config) clean-arm64-$(config) clean-arm-$(config))
endef
$(eval $(call ATMOSPHERE_ADD_TARGETS, nx, nx-hac-001, arm-cortex-a57,))
$(eval $(call ATMOSPHERE_ADD_TARGETS, nx_bpmp, nx-hac-001, arm7tdmi,))
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS), $(config) clean-$(config))

View File

@ -1,25 +1,42 @@
#---------------------------------------------------------------------------------
# Define the atmosphere board and cpu
#---------------------------------------------------------------------------------
export ATMOSPHERE_BOARD := nx-hac-001
export ATMOSPHERE_CPU := arm7tdmi
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
include $(CURRENT_DIRECTORY)/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS :=
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
endif
else
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -O2
endif
endif
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE -DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS
SETTINGS := $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -Wextra -Werror -fno-non-call-exceptions -Wno-array-bounds -Wno-stringop-overflow -Wno-stringop-overread
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
SETTINGS += -mgeneral-regs-only -ffixed-x18
else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm)
SETTINGS += -flto
endif
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -Wextra -Werror -flto -fno-non-call-exceptions \
-Wno-array-bounds \
-Wno-stringop-overflow \
-Wno-stringop-overread
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
@ -74,69 +91,28 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: release
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
-f $$(THIS_MAKEFILE)
clean-$(strip $1):
@echo clean $(strip $1) ...
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
.PHONY: $(strip $1) clean-$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS " \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_DEBUGGING" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_AUDITING" \
))
#---------------------------------------------------------------------------------
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
.PHONY: clean all
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_BUILD_DIR)/%:
@[ -d $@ ] || mkdir -p $@
all: $(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(SOURCES) $(INCLUDES) $(GCH_DIRS) $(CPPFILES) $(CFILES) $(SFILES)
@$(MAKE) __RECURSIVE__=1 OUTPUT=$(CURDIR)/$(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a \
DEPSDIR=$(CURDIR)/$(ATMOSPHERE_BUILD_DIR) \
--no-print-directory -C $(ATMOSPHERE_BUILD_DIR) \
-f $(THIS_MAKEFILE)
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
@echo clean $(ATMOSPHERE_BUILD_NAME) ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_OUT_DIR)
@rm -fr $(foreach hdr,$(GCH_DIRS),$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
$(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(GCH_DIRS):
@[ -d $@ ] || mkdir -p $@
#---------------------------------------------------------------------------------
else
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
#---------------------------------------------------------------------------------
@ -148,8 +124,12 @@ $(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin -fno-lto
util_api.o: CXXFLAGS += -fno-lto
libc.o: CFLAGS += -fno-builtin
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm)
libc.o: CFLAGS += -fno-lto
util_api.o: CFLAGS += -fno-lto
endif
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
@ -163,3 +143,4 @@ util_api.o: CXXFLAGS += -fno-lto
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,169 +1,42 @@
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: nx_release
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(CURRENT_DIRECTORY)/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS := include/mesosphere.hpp
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
SOURCES += $(foreach v,$(call ALL_SOURCE_DIRS,../libvapours/source),$(if $(findstring ../libvapours/source/sdmmc,$v),,$v))
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(__RECURSIVE__),1)
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: release
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
-f $$(THIS_MAKEFILE)
$(strip $1):
@echo "Building $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libmesosphere.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
clean-$(strip $1):
@echo clean $(strip $1) ...
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
.PHONY: $(strip $1) clean-$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
@echo "Cleaning $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libmesosphere.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
ATMOSPHERE_BUILD_SETTINGS="" \
define ATMOSPHERE_ADD_TARGETS
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_release, release, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4)" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_debug, debug, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_DEBUGGING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_audit, audit, $(strip $2), $(strip $3), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $4) -DAMS_BUILD_FOR_AUDITING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 ATMOSPHERE_BUILD_FOR_AUDITING=1 \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, qemu_virt_release, $(TARGET)_qemu_virt.a, \
ATMOSPHERE_BUILD_SETTINGS="" \
))
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, qemu_virt_debug, $(TARGET)_qemu_virt_debug.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
))
$(eval $(call ATMOSPHERE_ADD_TARGETS, nx, nx-hac-001, arm-cortex-a57,))
$(eval $(call ATMOSPHERE_ADD_TARGETS, qemu_virt_a57, qemu-virt, arm-cortex-a57,))
$(eval $(call ATMOSPHERE_ADD_TARGET, qemu_virt_audit, $(TARGET)_qemu_virt_audit.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
))
#---------------------------------------------------------------------------------
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
.PHONY: clean all
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
@[ -d $@ ] || mkdir -p $@
$(ATMOSPHERE_BUILD_DIR)/%:
@[ -d $@ ] || mkdir -p $@
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
#---------------------------------------------------------------------------------
else
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(filter-out kern_svc_tables.o, $(OFILES)) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
kern_libc_generic.o: CFLAGS += -fno-builtin
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS), $(config) clean-$(config))

View File

@ -24,6 +24,19 @@ namespace ams::kern {
}
namespace ams::diag {
NORETURN ALWAYS_INLINE void AssertionFailureImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
#if defined(MESOSPHERE_ENABLE_DEBUG_PRINT)
::ams::kern::Panic(file, line, "ams::diag::AssertionFailureImpl: %s:%s 0x%016" PRIx64 "", func, expr, value);
#else
::ams::kern::Panic();
AMS_UNUSED(file, line, func, expr, value);
#endif
}
}
#define MESOSPHERE_UNUSED(...) AMS_UNUSED(__VA_ARGS__)
#ifdef MESOSPHERE_ENABLE_DEBUG_PRINT

View File

@ -0,0 +1,123 @@
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(CURRENT_DIRECTORY)/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS := include/mesosphere.hpp
#PRECOMPILED_HEADERS :=
ifeq ($(ATMOSPHERE_BUILD_FOR_DEBUGGING),1)
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
else
ATMOSPHERE_OPTIMIZATION_FLAG := -Os
endif
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) $(ATMOSPHERE_OPTIMIZATION_FLAG) -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
SOURCES += $(foreach v,$(call ALL_SOURCE_DIRS,../libvapours/source),$(if $(findstring ../libvapours/source/sdmmc,$v),,$v))
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(__RECURSIVE__),1)
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
#---------------------------------------------------------------------------------
.PHONY: clean all
all: $(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(SOURCES) $(INCLUDES) $(GCH_DIRS) $(CPPFILES) $(CFILES) $(SFILES)
@$(MAKE) __RECURSIVE__=1 OUTPUT=$(CURDIR)/$(ATMOSPHERE_LIBRARY_DIR)/$(TARGET).a \
DEPSDIR=$(CURDIR)/$(ATMOSPHERE_BUILD_DIR) \
--no-print-directory -C $(ATMOSPHERE_BUILD_DIR) \
-f $(THIS_MAKEFILE)
#---------------------------------------------------------------------------------
clean:
@echo clean $(ATMOSPHERE_BUILD_NAME) ...
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_OUT_DIR)
@rm -fr $(foreach hdr,$(GCH_DIRS),$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
$(ATMOSPHERE_LIBRARY_DIR) $(ATMOSPHERE_BUILD_DIR) $(GCH_DIRS):
@[ -d $@ ] || mkdir -p $@
#---------------------------------------------------------------------------------
else
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(filter-out kern_svc_tables.o, $(OFILES)) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
kern_libc_generic.o: CFLAGS += -fno-builtin
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,145 +1,50 @@
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: nx_release
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(CURRENT_DIRECTORY)/../config/common.mk
#---------------------------------------------------------------------------------
# pull in switch rules
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
define ATMOSPHERE_ADD_TARGET
include $(DEVKITPRO)/libnx/switch_rules
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
#PRECOMPILED_HEADERS :=
$(strip $1):
@echo "Building $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libstratosphere.mk ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -Wextra -Werror -Wno-missing-field-initializers -flto
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
clean-$(strip $1):
@echo "Cleaning $(strip $1)"
@$$(MAKE) -f $(CURRENT_DIRECTORY)/libstratosphere.mk clean ATMOSPHERE_MAKEFILE_TARGET="$(strip $1)" ATMOSPHERE_BUILD_NAME="$(strip $2)" ATMOSPHERE_BOARD="$(strip $3)" ATMOSPHERE_CPU="$(strip $4)" $(strip $5)
LDFLAGS := -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) -Wl,-Map,$(notdir $*.map)
endef
SOURCES += $(call ALL_SOURCE_DIRS,../libvapours/source)
SOURCES += $(call UNFILTERED_SOURCE_DIRS,source/os)
define ATMOSPHERE_ADD_TARGETS
LIBS := -lnx
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_release, $(strip $2)release, $(strip $3), $(strip $4), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $5)" $(strip $6) \
))
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX) $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_debug, $(strip $2)debug, $(strip $3), $(strip $4), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $5) -DAMS_BUILD_FOR_DEBUGGING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 $(strip $6) \
))
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
$(eval $(call ATMOSPHERE_ADD_TARGET, $(strip $1)_audit, $(strip $2)audit, $(strip $3), $(strip $4), \
ATMOSPHERE_BUILD_SETTINGS="$(strip $5) -DAMS_BUILD_FOR_AUDITING" ATMOSPHERE_BUILD_FOR_DEBUGGING=1 ATMOSPHERE_BUILD_FOR_AUDITING=1 $(strip $6) \
))
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
endef
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
$(eval $(call ATMOSPHERE_ADD_TARGETS, nx, , nx-hac-001, arm-cortex-a57,,))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
$(eval $(call ATMOSPHERE_ADD_TARGETS, win_x64, , generic_windows, generic_x64,,))
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export GCH_FILES := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
$(eval $(call ATMOSPHERE_ADD_TARGETS, linux_x64, , generic_linux, generic_x64,,))
$(eval $(call ATMOSPHERE_ADD_TARGETS, linux_x64_clang, clang_, generic_linux, generic_x64,, ATMOSPHERE_COMPILER_NAME="clang"))
$(eval $(call ATMOSPHERE_ADD_TARGETS, linux_arm64_clang, clang_, generic_linux, generic_arm64,, ATMOSPHERE_COMPILER_NAME="clang"))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
$(eval $(call ATMOSPHERE_ADD_TARGETS, macos_x64, , generic_macos, generic_x64,,))
$(eval $(call ATMOSPHERE_ADD_TARGETS, macos_arm64, , generic_macos, generic_arm64,,))
.PHONY: clean all lib/$(TARGET).a
#---------------------------------------------------------------------------------
all: lib/$(TARGET).a
lib:
@[ -d $@ ] || mkdir -p $@
release:
@[ -d $@ ] || mkdir -p $@
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
dist-bin: all
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
dist-src:
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
dist: dist-src dist-bin
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release lib *.bz2 $(GCH_FILES)
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES:.hpp.gch=.d),$(notdir $(hdr)))
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
ams_environment_weak.o: CXXFLAGS += -fno-lto
hos_version_api_weak_for_unit_test.o: CXXFLAGS += -fno-lto
pm_info_api_weak.o: CXXFLAGS += -fno-lto
hos_stratosphere_api.o: CXXFLAGS += -fno-lto
init_operator_new.o: CXXFLAGS += -fno-lto
init_libnx_shim.os.horizon.o: CXXFLAGS += -fno-lto
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------
clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config))
.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS), $(config) clean-$(config))

View File

@ -16,9 +16,18 @@
#pragma once
/* Ensure that on windows we use lean-windows headers. */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
/* libvapours (pulls in util, svc, results). */
#include <vapours.hpp>
#if defined(ATMOSPHERE_OS_WINDOWS)
#include <stratosphere/windows.hpp>
#endif
/* Libstratosphere diagnostics. */
#include <stratosphere/diag.hpp>

View File

@ -20,7 +20,9 @@
namespace ams {
/* Will be called by libstratosphere on crash. */
#if defined(ATMOSPHERE_OS_HORIZON)
void CrashHandler(ThreadExceptionDump *ctx);
#endif
/* API for boot sysmodule. */
void InitializeForBoot();

View File

@ -21,6 +21,7 @@ namespace ams::exosphere {
ApiInfo GetApiInfo();
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
void ForceRebootToRcm();
void ForceRebootToIramPayload();
void ForceRebootToFatalError();
@ -35,6 +36,7 @@ namespace ams::exosphere {
void CopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size);
void CopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size);
#endif
}

View File

@ -40,7 +40,10 @@ namespace ams::capsrv {
}
};
static_assert(sizeof(ScreenShotDecodeOption) == 0x20);
static_assert(sizeof(ScreenShotDecodeOption) == sizeof(::CapsScreenShotDecodeOption));
static_assert(util::is_pod<ScreenShotDecodeOption>::value);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(ScreenShotDecodeOption) == sizeof(::CapsScreenShotDecodeOption));
#endif
}

View File

@ -30,10 +30,12 @@ namespace ams::cfg {
OverrideStatusFlag_AddressSpaceShift = 3,
OverrideStatusFlag_AddressSpaceMask = ((1u << 2) - 1) << OverrideStatusFlag_AddressSpaceShift,
#if defined(ATMOSPHERE_OS_HORIZON)
OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift,
#endif
};
}
@ -63,7 +65,11 @@ namespace ams::cfg {
static_assert(util::is_pod<OverrideStatus>::value, "util::is_pod<OverrideStatus>::value");
constexpr inline bool operator==(const OverrideStatus &lhs, const OverrideStatus &rhs) {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(lhs)) == 0;
if (std::is_constant_evaluated()) {
return lhs.keys_held == rhs.keys_held && lhs.flags == rhs.flags;
} else {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(lhs)) == 0;
}
}
constexpr inline bool operator!=(const OverrideStatus &lhs, const OverrideStatus &rhs) {

View File

@ -19,8 +19,12 @@
namespace ams::dd {
#if defined(ATMOSPHERE_OS_HORIZON)
using DeviceName = ::ams::svc::DeviceName;
using enum ::ams::svc::DeviceName;
#else
enum DeviceName { };
#endif
constexpr inline u64 DeviceAddressSpaceMemoryRegionAlignment = 4_KB;

View File

@ -81,7 +81,7 @@ namespace ams::ddsf {
m_session_list.clear();
}
protected:
~IDevice() {
virtual ~IDevice() {
m_session_list.clear();
}
public:

View File

@ -40,7 +40,7 @@ namespace ams::ddsf {
m_device_list.clear();
}
protected:
~IDriver() {
virtual ~IDriver() {
m_device_list.clear();
}
public:

View File

@ -53,7 +53,7 @@ namespace ams::ddsf {
public:
IEventHandler() : m_holder(), m_user_data(0), m_is_initialized(false), m_is_registered(false) { /* ... */ }
~IEventHandler() {
virtual ~IEventHandler() {
if (this->IsRegistered()) {
this->Unlink();
}

View File

@ -58,7 +58,7 @@ namespace ams::ddsf {
public:
ISession() : m_list_node(), m_device(nullptr), m_access_mode() { /* ... */ }
protected:
~ISession() { this->DetachDevice(); AMS_ASSERT(!this->IsOpen()); }
virtual ~ISession() { this->DetachDevice(); AMS_ASSERT(!this->IsOpen()); }
public:
void AddTo(List &list) {
list.push_back(*this);

View File

@ -42,13 +42,13 @@ namespace ams::ddsf::impl {
public:
#if !(defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING))
constexpr TypeTag() : m_class_name(nullptr), m_base(nullptr) { /* ... */}
constexpr TypeTag(const TypeTag &b) : m_class_name(nullptr), m_base(std::addressof(b)) { AMS_ASSERT(this != m_base); }
constexpr TypeTag(const TypeTag &b) : m_class_name(nullptr), m_base(std::addressof(b)) { if (!std::is_constant_evaluated()) { AMS_ASSERT(this != m_base); } }
constexpr TypeTag(const char *c) : m_class_name(nullptr), m_base(nullptr) { AMS_UNUSED(c); }
constexpr TypeTag(const char *c, const TypeTag &b) : m_class_name(nullptr), m_base(std::addressof(b)) { AMS_UNUSED(c); AMS_ASSERT(this != m_base); }
constexpr TypeTag(const char *c, const TypeTag &b) : m_class_name(nullptr), m_base(std::addressof(b)) { if (!std::is_constant_evaluated()) { AMS_UNUSED(c); AMS_ASSERT(this != m_base); } }
#else
constexpr TypeTag(const char *c) : m_class_name(c), m_base(nullptr) { /* ... */ }
constexpr TypeTag(const char *c, const TypeTag &b) : m_class_name(c), m_base(std::addressof(b)) { AMS_ASSERT(this != m_base); }
constexpr TypeTag(const char *c, const TypeTag &b) : m_class_name(c), m_base(std::addressof(b)) { if (!std::is_constant_evaluated()) { AMS_ASSERT(this != m_base); } }
#endif
constexpr const char * GetClassName() const { return m_class_name; }

View File

@ -21,6 +21,13 @@
namespace ams::fatal {
enum FatalPolicy {
FatalPolicy_ErrorReportAndErrorScreen = 0,
FatalPolicy_ErrorReport = 1,
FatalPolicy_ErrorScreen = 2
};
#if defined(ATMOSPHERE_ARCH_ARM64)
namespace aarch64 {
enum RegisterName {
@ -150,7 +157,7 @@ namespace ams::fatal {
void SetProgramIdForAtmosphere(ncm::ProgramId program_id) {
/* Right now, we mux program ID in through afsr when creport. */
/* TODO: Better way to do this? */
this->afsr0 = static_cast<RegisterType>(program_id);
this->afsr0 = static_cast<RegisterType>(program_id.value);
}
ncm::ProgramId GetProgramIdForAtmosphere() const {
@ -172,7 +179,9 @@ namespace ams::fatal {
};
}
#endif
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
namespace aarch32 {
enum RegisterName {
@ -268,8 +277,8 @@ namespace ams::fatal {
void SetProgramIdForAtmosphere(ncm::ProgramId program_id) {
/* Right now, we mux program ID in through afsr when creport. */
/* TODO: Better way to do this? */
this->afsr0 = static_cast<RegisterType>(static_cast<u64>(program_id) >> 0);
this->afsr1 = static_cast<RegisterType>(static_cast<u64>(program_id) >> 32);
this->afsr0 = static_cast<RegisterType>(static_cast<u64>(program_id.value) >> 0);
this->afsr1 = static_cast<RegisterType>(static_cast<u64>(program_id.value) >> 32);
}
ncm::ProgramId GetProgramIdForAtmosphere() const {
@ -291,16 +300,158 @@ namespace ams::fatal {
};
}
#endif
#if defined(ATMOSPHERE_ARCH_X64)
namespace x64 {
enum RegisterName {
/* TODO */
RegisterName_Count,
};
struct CpuContext {
using RegisterType = u64;
static constexpr size_t MaxStackTraceDepth = 0x20;
static constexpr const char *RegisterNameStrings[RegisterName_Count] = {
/* TODO */
};
/* Registers, exception context. N left names for these fields in fatal .rodata. */
union {
// struct {
// /* TODO */
// };
RegisterType registers[RegisterName_Count];
};
/* Misc. */
RegisterType stack_trace[MaxStackTraceDepth];
RegisterType base_address;
RegisterType register_set_flags;
u32 stack_trace_size;
void ClearState() {
std::memset(this, 0, sizeof(*this));
}
void SetProgramIdForAtmosphere(ncm::ProgramId program_id) {
AMS_UNUSED(program_id);
AMS_ABORT("TODO");
}
ncm::ProgramId GetProgramIdForAtmosphere() const {
AMS_ABORT("TODO");
}
void SetRegisterValue(RegisterName name, RegisterType value) {
this->registers[name] = value;
this->register_set_flags |= (RegisterType(1) << name);
}
bool HasRegisterValue(RegisterName name) const {
return this->register_set_flags & (RegisterType(1) << name);
}
void SetBaseAddress(RegisterType base_addr) {
this->base_address = base_addr;
}
};
}
#endif
#if defined(ATMOSPHERE_ARCH_X64) || defined(ATMOSPHERE_ARCH_X86)
namespace x86 {
enum RegisterName {
/* TODO */
RegisterName_Count,
};
struct CpuContext {
using RegisterType = u32;
static constexpr size_t MaxStackTraceDepth = 0x20;
static constexpr const char *RegisterNameStrings[RegisterName_Count] = {
/* TODO */
};
/* Registers, exception context. N left names for these fields in fatal .rodata. */
union {
// struct {
// /* TODO */
// };
RegisterType registers[RegisterName_Count];
};
/* Misc. Yes, stack_trace_size is really laid out differently than aarch64... */
RegisterType stack_trace[MaxStackTraceDepth];
u32 stack_trace_size;
RegisterType base_address;
RegisterType register_set_flags;
void ClearState() {
std::memset(this, 0, sizeof(*this));
}
void SetProgramIdForAtmosphere(ncm::ProgramId program_id) {
AMS_UNUSED(program_id);
AMS_ABORT("TODO");
}
ncm::ProgramId GetProgramIdForAtmosphere() const {
AMS_ABORT("TODO");
}
void SetRegisterValue(RegisterName name, RegisterType value) {
this->registers[name] = value;
this->register_set_flags |= (RegisterType(1) << name);
}
bool HasRegisterValue(RegisterName name) const {
return this->register_set_flags & (RegisterType(1) << name);
}
void SetBaseAddress(RegisterType base_addr) {
this->base_address = base_addr;
}
};
}
#endif
struct CpuContext : sf::LargeData, sf::PrefersMapAliasTransferMode {
enum Architecture {
Architecture_Aarch64 = 0,
Architecture_Aarch32 = 1,
#if defined(ATMOSPHERE_ARCH_ARM64)
Architecture_Aarch64,
#endif
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
Architecture_Aarch32,
#endif
#if defined(ATMOSPHERE_X64)
Architecture_X64,
#endif
#if defined(ATMOSPHERE_X64) || defined(ATMOSPHERE_ARCH_X86)
Architecture_X86,
#endif
};
union {
#if defined(ATMOSPHERE_ARCH_ARM64)
aarch64::CpuContext aarch64_ctx;
#endif
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
aarch32::CpuContext aarch32_ctx;
#endif
#if defined(ATMOSPHERE_X64)
aarch64::CpuContext x64_ctx;
#endif
#if defined(ATMOSPHERE_X64) || defined(ATMOSPHERE_ARCH_X86)
aarch64::CpuContext x86_ctx;
#endif
u8 raw_storage[0x248];
};
Architecture architecture;
@ -311,8 +462,12 @@ namespace ams::fatal {
}
};
#if defined(ATMOSPHERE_ARCH_ARM64)
static_assert(util::is_pod<aarch64::CpuContext>::value && sizeof(aarch64::CpuContext) == 0x248, "aarch64::CpuContext definition!");
#endif
#if defined(ATMOSPHERE_ARCH_ARM64) || defined(ATMOSPHERE_ARCH_ARM)
static_assert(util::is_pod<aarch32::CpuContext>::value && sizeof(aarch32::CpuContext) == 0xE0, "aarch32::CpuContext definition!");
#endif
static_assert(util::is_pod<CpuContext>::value && sizeof(CpuContext) == 0x250, "CpuContext definition!");
namespace srv {

View File

@ -20,8 +20,8 @@
#include <stratosphere/sf.hpp>
#define AMS_FATAL_I_SERVICE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, ThrowFatal, (Result error, const sf::ClientProcessId &client_pid), (error, client_pid)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, ThrowFatalWithPolicy, (Result error, const sf::ClientProcessId &client_pid, FatalPolicy policy), (error, client_pid, policy)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, ThrowFatalWithCpuContext, (Result error, const sf::ClientProcessId &client_pid, FatalPolicy policy, const fatal::CpuContext &cpu_ctx), (error, client_pid, policy, cpu_ctx))
AMS_SF_METHOD_INFO(C, H, 0, Result, ThrowFatal, (Result error, const sf::ClientProcessId &client_pid), (error, client_pid)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, ThrowFatalWithPolicy, (Result error, const sf::ClientProcessId &client_pid, fatal::FatalPolicy policy), (error, client_pid, policy)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, ThrowFatalWithCpuContext, (Result error, const sf::ClientProcessId &client_pid, fatal::FatalPolicy policy, const fatal::CpuContext &cpu_ctx), (error, client_pid, policy, cpu_ctx))
AMS_SF_DEFINE_INTERFACE(ams::fatal::impl, IService, AMS_FATAL_I_SERVICE_INTERFACE_INFO)

View File

@ -41,7 +41,9 @@
#include <stratosphere/fs/fs_speed_emulation.hpp>
#include <stratosphere/fs/impl/fs_common_mount_name.hpp>
#include <stratosphere/fs/fs_mount.hpp>
#include <stratosphere/fs/fs_path_utils.hpp>
#include <stratosphere/fs/fs_path_utility.hpp>
#include <stratosphere/fs/fs_path.hpp>
#include <stratosphere/fs/common/fs_directory_path_parser.hpp>
#include <stratosphere/fs/fs_filesystem_utils.hpp>
#include <stratosphere/fs/fs_romfs_filesystem.hpp>
#include <stratosphere/fs/impl/fs_data.hpp>
@ -50,8 +52,9 @@
#include <stratosphere/fs/fs_code.hpp>
#include <stratosphere/fs/fs_content.hpp>
#include <stratosphere/fs/fs_content_storage.hpp>
#include <stratosphere/fs/fs_image_directory.hpp>
#include <stratosphere/fs/fs_game_card.hpp>
#include <stratosphere/fs/fs_host.hpp>
#include <stratosphere/fs/fs_image_directory.hpp>
#include <stratosphere/fs/fs_save_data_types.hpp>
#include <stratosphere/fs/fs_save_data_management.hpp>
#include <stratosphere/fs/fs_save_data_transaction.hpp>

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fs {
class DirectoryPathParser {
NON_COPYABLE(DirectoryPathParser);
NON_MOVEABLE(DirectoryPathParser);
private:
char *m_buffer;
char m_replaced_char;
s32 m_position;
fs::Path m_current_path;
public:
DirectoryPathParser() : m_buffer(nullptr), m_replaced_char(StringTraits::NullTerminator), m_position(0), m_current_path() { /* ... */ }
const fs::Path &GetCurrentPath() const {
return m_current_path;
}
Result Initialize(fs::Path *path) {
/* Declare a default buffer, in case the path has no write buffer. */
static constinit char EmptyBuffer[1] = "";
/* Get a usable buffer. */
char *buf = path->GetWriteBufferLength() > 0 ? path->GetWriteBuffer() : EmptyBuffer;
/* Get the windows skip length. */
const auto windows_skip_len = fs::GetWindowsSkipLength(buf);
/* Set our buffer. */
m_buffer = buf + windows_skip_len;
/* Set up our initial state. */
if (windows_skip_len) {
R_TRY(m_current_path.InitializeWithNormalization(buf, windows_skip_len + 1));
} else {
if (char * const first = this->ReadNextImpl(); first != nullptr) {
R_TRY(m_current_path.InitializeWithNormalization(first));
}
}
R_SUCCEED();
}
Result ReadNext(bool *out_finished) {
/* Default to not finished. */
*out_finished = false;
/* Get the next child component. */
if (auto * const child = this->ReadNextImpl(); child != nullptr) {
/* Append the child component to our current path. */
R_TRY(m_current_path.AppendChild(child));
} else {
/* We have no child component, so we're finished. */
*out_finished = true;
}
R_SUCCEED();
}
private:
char *ReadNextImpl() {
/* Check that we have characters to read. */
if (m_position < 0 || m_buffer[0] == StringTraits::NullTerminator) {
return nullptr;
}
/* If we have a replaced character, restore it. */
if (m_replaced_char != StringTraits::NullTerminator) {
m_buffer[m_position] = m_replaced_char;
if (m_replaced_char == StringTraits::DirectorySeparator) {
++m_position;
}
}
/* If we're at the start of a root-relative path, begin by returning the root. */
if (m_position == 0 && m_buffer[0] == StringTraits::DirectorySeparator) {
m_replaced_char = m_buffer[1];
m_buffer[1] = StringTraits::NullTerminator;
m_position = 1;
return m_buffer;
}
/* Otherwise, find the end of the next path component. */
s32 i;
for (i = m_position; m_buffer[i] != StringTraits::DirectorySeparator; ++i) {
if (m_buffer[i] == StringTraits::NullTerminator) {
if (i == m_position) {
m_position = -1;
return nullptr;
}
}
}
/* Sanity check that we're not ending on a separator. */
AMS_ASSERT(m_buffer[i + 1] != StringTraits::NullTerminator);
char * const ret = m_buffer + m_position;
m_replaced_char = StringTraits::DirectorySeparator;
m_buffer[i] = 0;
m_position = i;
return ret;
}
};
}

View File

@ -82,7 +82,7 @@ namespace ams::fs {
public:
constexpr FileStorageBasedFileSystem() : FileStorage(), m_base_file_system(nullptr) { /* ... */ }
Result Initialize(std::shared_ptr<fs::fsa::IFileSystem> base_file_system, const char *path, fs::OpenMode mode);
Result Initialize(std::shared_ptr<fs::fsa::IFileSystem> base_file_system, const fs::Path &path, fs::OpenMode mode);
};
class FileHandleStorage : public IStorage, public impl::Newable {

View File

@ -20,7 +20,13 @@ namespace ams::fs {
constexpr inline size_t EntryNameLengthMax = 0x300;
using DirectoryEntry = ::FsDirectoryEntry;
struct DirectoryEntry {
char name[EntryNameLengthMax + 1];
char pad[3];
s8 type;
u8 pad2[3];
s64 file_size;
};
struct DirectoryHandle {
void *handle;

View File

@ -24,7 +24,11 @@ namespace ams::fs {
static const ReadOption None;
};
inline constexpr const ReadOption ReadOption::None = {FsReadOption_None};
enum ReadOptionFlag : u32 {
ReadOptionFlag_None = (0 << 0),
};
inline constexpr const ReadOption ReadOption::None = {ReadOptionFlag_None};
inline constexpr bool operator==(const ReadOption &lhs, const ReadOption &rhs) {
return lhs._value == rhs._value;
@ -36,19 +40,24 @@ namespace ams::fs {
static_assert(util::is_pod<ReadOption>::value && sizeof(ReadOption) == sizeof(u32));
enum WriteOptionFlag : u32 {
WriteOptionFlag_None = (0 << 0),
WriteOptionFlag_Flush = (1 << 0),
};
struct WriteOption {
u32 _value;
constexpr inline bool HasFlushFlag() const {
return _value & FsWriteOption_Flush;
return _value & WriteOptionFlag_Flush;
}
static const WriteOption None;
static const WriteOption Flush;
};
inline constexpr const WriteOption WriteOption::None = {FsWriteOption_None};
inline constexpr const WriteOption WriteOption::Flush = {FsWriteOption_Flush};
inline constexpr const WriteOption WriteOption::None = {WriteOptionFlag_None};
inline constexpr const WriteOption WriteOption::Flush = {WriteOptionFlag_Flush};
inline constexpr bool operator==(const WriteOption &lhs, const WriteOption &rhs) {
return lhs._value == rhs._value;

View File

@ -25,8 +25,8 @@ namespace ams::fs {
}
enum OpenMode {
OpenMode_Read = (1 << 0),
OpenMode_Write = (1 << 1),
OpenMode_Read = (1 << 0),
OpenMode_Write = (1 << 1),
OpenMode_AllowAppend = (1 << 2),
OpenMode_ReadWrite = (OpenMode_Read | OpenMode_Write),
@ -34,23 +34,23 @@ namespace ams::fs {
};
enum OpenDirectoryMode {
OpenDirectoryMode_Directory = ::FsDirOpenMode_ReadDirs,
OpenDirectoryMode_File = ::FsDirOpenMode_ReadFiles,
OpenDirectoryMode_Directory = (1 << 0),
OpenDirectoryMode_File = (1 << 1),
OpenDirectoryMode_All = (OpenDirectoryMode_Directory | OpenDirectoryMode_File),
/* TODO: Separate enum, like N? */
OpenDirectoryMode_NotRequireFileSize = ::FsDirOpenMode_NoFileSize,
OpenDirectoryMode_NotRequireFileSize = (1 << 31),
};
enum DirectoryEntryType {
DirectoryEntryType_Directory = ::FsDirEntryType_Dir,
DirectoryEntryType_File = ::FsDirEntryType_File,
DirectoryEntryType_Directory = 0,
DirectoryEntryType_File = 1,
};
enum CreateOption {
CreateOption_None = 0,
CreateOption_BigFile = ::FsCreateOption_BigFile,
CreateOption_None = (0 << 0),
CreateOption_BigFile = (1 << 0),
};
struct FileHandle;

View File

@ -16,10 +16,37 @@
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/time/time_posix_time.hpp>
namespace ams::fs {
using FileTimeStampRaw = ::FsTimeStampRaw;
struct FileTimeStamp {
time::PosixTime create;
time::PosixTime modify;
time::PosixTime access;
bool is_local_time;
char pad[7];
};
static_assert(util::is_pod<FileTimeStamp>::value && sizeof(FileTimeStamp) == 0x20);
struct FileTimeStampRaw {
s64 create;
s64 modify;
s64 access;
bool is_local_time;
char pad[7];
};
static_assert(util::is_pod<FileTimeStampRaw>::value && sizeof(FileTimeStampRaw) == 0x20);
static_assert(__builtin_offsetof(FileTimeStampRaw, create) == __builtin_offsetof(FileTimeStampRaw, create));
static_assert(__builtin_offsetof(FileTimeStampRaw, modify) == __builtin_offsetof(FileTimeStampRaw, modify));
static_assert(__builtin_offsetof(FileTimeStampRaw, access) == __builtin_offsetof(FileTimeStampRaw, access));
static_assert(__builtin_offsetof(FileTimeStampRaw, is_local_time) == __builtin_offsetof(FileTimeStampRaw, is_local_time));
static_assert(__builtin_offsetof(FileTimeStampRaw, pad) == __builtin_offsetof(FileTimeStampRaw, pad));
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
#endif
namespace impl {
@ -27,6 +54,6 @@ namespace ams::fs {
}
Result GetFileTimeStampRawForDebug(FileTimeStampRaw *out, const char *path);
Result GetFileTimeStamp(FileTimeStamp *out, const char *path);
}

View File

@ -21,8 +21,8 @@
namespace ams::fs {
/* Common utilities. */
Result EnsureDirectoryRecursively(const char *path);
Result EnsureParentDirectoryRecursively(const char *path);
Result EnsureDirectory(const char *path);
Result EnsureParentDirectory(const char *path);
Result HasFile(bool *out, const char *path);
Result HasDirectory(bool *out, const char *path);

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/fs/fs_code_verification_data.hpp>
namespace ams::fs {
enum MountHostOptionFlag : u32 {
MountHostOptionFlag_None = (0 << 0),
MountHostOptionFlag_PseudoCaseSensitive = (1 << 0),
};
struct MountHostOption {
u32 _value;
constexpr inline bool HasPseudoCaseSensitiveFlag() const {
return _value & MountHostOptionFlag_PseudoCaseSensitive;
}
static const MountHostOption None;
static const MountHostOption PseudoCaseSensitive;
};
inline constexpr const MountHostOption MountHostOption::None = {MountHostOptionFlag_None};
inline constexpr const MountHostOption MountHostOption::PseudoCaseSensitive = {MountHostOptionFlag_PseudoCaseSensitive};
inline constexpr bool operator==(const MountHostOption &lhs, const MountHostOption &rhs) {
return lhs._value == rhs._value;
}
inline constexpr bool operator!=(const MountHostOption &lhs, const MountHostOption &rhs) {
return !(lhs == rhs);
}
Result MountHost(const char *name, const char *root_path);
Result MountHost(const char *name, const char *root_path, const MountHostOption &option);
Result MountHostRoot();
Result MountHostRoot(const MountHostOption &option);
void UnmountHostRoot();
}

View File

@ -68,13 +68,13 @@ namespace ams::fs {
std::unique_ptr<IStorage> m_unique_storage;
IStorage *m_storage;
public:
ReadOnlyStorageAdapter(IStorage *s) : m_unique_storage(s) {
explicit ReadOnlyStorageAdapter(IStorage *s) : m_unique_storage(s) {
m_storage = m_unique_storage.get();
}
ReadOnlyStorageAdapter(std::shared_ptr<IStorage> s) : m_shared_storage(s) {
explicit ReadOnlyStorageAdapter(std::shared_ptr<IStorage> s) : m_shared_storage(s) {
m_storage = m_shared_storage.get();
}
ReadOnlyStorageAdapter(std::unique_ptr<IStorage> s) : m_unique_storage(std::move(s)) {
explicit ReadOnlyStorageAdapter(std::unique_ptr<IStorage> s) : m_unique_storage(std::move(s)) {
m_storage = m_unique_storage.get();
}

View File

@ -0,0 +1,582 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_memory_management.hpp>
#include <stratosphere/fs/impl/fs_common_mount_name.hpp>
#include <stratosphere/fs/fs_path_utility.hpp>
namespace ams::fs {
class DirectoryPathParser;
class Path {
NON_COPYABLE(Path);
NON_MOVEABLE(Path);
private:
static constexpr const char *EmptyPath = "";
static constexpr size_t WriteBufferAlignmentLength = 8;
private:
friend class DirectoryPathParser;
private:
using WriteBuffer = std::unique_ptr<char[], ::ams::fs::impl::Deleter>;
private:
const char *m_str;
util::TypedStorage<WriteBuffer> m_write_buffer;
size_t m_write_buffer_length;
bool m_is_normalized;
public:
Path() : m_str(EmptyPath), m_write_buffer_length(0), m_is_normalized(false) {
util::ConstructAt(m_write_buffer, nullptr);
}
constexpr Path(const char *s, util::ConstantInitializeTag) : m_str(s), m_write_buffer(), m_write_buffer_length(0), m_is_normalized(true) {
/* ... */
}
constexpr ~Path() {
if (!std::is_constant_evaluated()) {
util::DestroyAt(m_write_buffer);
}
}
WriteBuffer ReleaseBuffer() {
/* Check pre-conditions. */
AMS_ASSERT(util::GetReference(m_write_buffer) != nullptr);
/* Reset. */
m_str = EmptyPath;
m_write_buffer_length = 0;
/* Return our write buffer. */
return std::move(util::GetReference(m_write_buffer));
}
constexpr Result SetShallowBuffer(const char *buffer) {
/* Check pre-conditions. */
AMS_ASSERT(m_write_buffer_length == 0);
/* Check the buffer is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
/* Set buffer. */
this->SetReadOnlyBuffer(buffer);
/* Note that we're normalized. */
m_is_normalized = true;
R_SUCCEED();
}
const char *GetString() const {
/* Check pre-conditions. */
AMS_ASSERT(m_is_normalized);
return m_str;
}
size_t GetLength() const {
return std::strlen(this->GetString());
}
bool IsEmpty() const {
return *m_str == '\x00';
}
bool IsMatchHead(const char *p, size_t len) const {
return util::Strncmp(this->GetString(), p, len) == 0;
}
Result Initialize(const Path &rhs) {
/* Check the other path is normalized. */
R_UNLESS(rhs.m_is_normalized, fs::ResultNotNormalized());
/* Allocate buffer for our path. */
const auto len = rhs.GetLength();
R_TRY(this->Preallocate(len + 1));
/* Copy the path. */
const size_t copied = util::Strlcpy<char>(util::GetReference(m_write_buffer).get(), rhs.GetString(), len + 1);
R_UNLESS(copied == len, fs::ResultUnexpectedInPathA());
/* Set normalized. */
m_is_normalized = rhs.m_is_normalized;
R_SUCCEED();
}
Result Initialize(const char *path, size_t len) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, len));
/* Set not normalized. */
m_is_normalized = false;
R_SUCCEED();
}
Result Initialize(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
return this->Initialize(path, std::strlen(path));
}
Result InitializeWithFormat(const char *fmt, ...) __attribute__((format (printf, 2, 3))) {
/* Check the format string is valid. */
R_UNLESS(fmt != nullptr, fs::ResultNullptrArgument());
/* Create the va_list for formatting. */
std::va_list vl;
va_start(vl, fmt);
/* Determine how big the string will be. */
char dummy;
const auto len = util::VSNPrintf(std::addressof(dummy), 0, fmt, vl);
/* Allocate buffer for our path. */
R_TRY(this->Preallocate(len + 1));
/* Format our path into our new buffer. */
const auto real_len = util::VSNPrintf(util::GetReference(m_write_buffer).get(), m_write_buffer_length, fmt, vl);
AMS_ASSERT(real_len == len);
AMS_UNUSED(real_len);
/* Finish the va_list. */
va_end(vl);
/* Set not normalized. */
m_is_normalized = false;
R_SUCCEED();
}
Result InitializeWithReplaceBackslash(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Replace slashes as desired. */
if (m_write_buffer_length > 1) {
fs::Replace(this->GetWriteBuffer(), m_write_buffer_length - 1, '\\', '/');
}
/* Set not normalized. */
m_is_normalized = false;
R_SUCCEED();
}
Result InitializeWithReplaceForwardSlashes(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Replace slashes as desired. */
if (m_write_buffer_length > 1) {
if (auto *p = this->GetWriteBuffer(); p[0] == '/' && p[1] == '/') {
p[0] = '\\';
p[1] = '\\';
}
}
/* Set not normalized. */
m_is_normalized = false;
R_SUCCEED();
}
Result InitializeWithReplaceUnc(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, std::strlen(path)));
/* Set not normalized. */
m_is_normalized = false;
/* Replace unc as desired. */
if (m_str[0]) {
auto *p = this->GetWriteBuffer();
/* Replace :/// -> \\ as needed. */
if (auto *sep = std::strstr(p, ":///"); sep != nullptr) {
sep[0] = '\\';
sep[1] = '\\';
}
/* Edit path prefix. */
if (!util::Strncmp(p, AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME AMS_FS_IMPL_MOUNT_NAME_DELIMITER "/", AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN + 1)) {
static_assert((AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME AMS_FS_IMPL_MOUNT_NAME_DELIMITER)[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 1] == '/');
p[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 1] = '\\';
p[AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN + AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN - 0] = '\\';
}
if (p[0] == '/' && p[1] == '/') {
p[0] = '\\';
p[1] = '\\';
}
}
R_SUCCEED();
}
Result InitializeWithNormalization(const char *path, size_t size) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
/* Initialize. */
R_TRY(this->InitializeImpl(path, size));
/* Set not normalized. */
m_is_normalized = false;
/* Perform normalization. */
fs::PathFlags path_flags;
if (fs::IsPathRelative(m_str)) {
path_flags.AllowRelativePath();
} else if (fs::IsWindowsPath(m_str, true)) {
path_flags.AllowWindowsPath();
} else {
/* NOTE: In this case, Nintendo checks is normalized, then sets is normalized, then returns success. */
/* This seems like a bug. */
size_t dummy;
R_TRY(PathFormatter::IsNormalized(std::addressof(m_is_normalized), std::addressof(dummy), m_str));
m_is_normalized = true;
R_SUCCEED();
}
/* Normalize. */
R_TRY(this->Normalize(path_flags));
m_is_normalized = true;
R_SUCCEED();
}
Result InitializeWithNormalization(const char *path) {
/* Check the path is valid. */
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
R_RETURN(this->InitializeWithNormalization(path, std::strlen(path)));
}
Result InitializeAsEmpty() {
/* Clear our buffer. */
this->ClearBuffer();
/* Set normalized. */
m_is_normalized = true;
R_SUCCEED();
}
Result AppendChild(const char *child) {
/* Check the path is valid. */
R_UNLESS(child != nullptr, fs::ResultNullptrArgument());
/* Basic checks. If we hvea a path and the child is empty, we have nothing to do. */
const char *c = child;
if (m_str[0]) {
/* Skip an early separator. */
if (*c == '/') {
++c;
}
R_SUCCEED_IF(*c == '\x00');
}
/* If we don't have a string, we can just initialize. */
auto cur_len = std::strlen(m_str);
if (cur_len == 0) {
R_RETURN(this->Initialize(child));
}
/* Remove a trailing separator. */
if (m_str[cur_len - 1] == '/' || m_str[cur_len - 1] == '\\') {
--cur_len;
}
/* Get the child path's length. */
auto child_len = std::strlen(c);
/* Reset our write buffer. */
WriteBuffer old_write_buffer;
if (util::GetReference(m_write_buffer) != nullptr) {
old_write_buffer = std::move(util::GetReference(m_write_buffer));
this->ClearBuffer();
}
/* Pre-allocate the new buffer. */
R_TRY(this->Preallocate(cur_len + 1 + child_len + 1));
/* Get our write buffer. */
auto *dst = this->GetWriteBuffer();
if (old_write_buffer != nullptr && cur_len > 0) {
util::Strlcpy<char>(dst, old_write_buffer.get(), cur_len + 1);
}
/* Add separator. */
dst[cur_len] = '/';
/* Copy the child path. */
const size_t copied = util::Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
R_UNLESS(copied == child_len, fs::ResultUnexpectedInPathA());
R_SUCCEED();
}
Result AppendChild(const Path &rhs) {
R_RETURN(this->AppendChild(rhs.GetString()));
}
Result Combine(const Path &parent, const Path &child) {
/* Get the lengths. */
const auto p_len = parent.GetLength();
const auto c_len = child.GetLength();
/* Allocate our buffer. */
R_TRY(this->Preallocate(p_len + c_len + 1));
/* Initialize as parent. */
R_TRY(this->Initialize(parent));
/* If we're empty, we can just initialize as child. */
if (this->IsEmpty()) {
R_TRY(this->Initialize(child));
} else {
/* Otherwise, we should append the child. */
R_TRY(this->AppendChild(child));
}
R_SUCCEED();
}
Result RemoveChild() {
/* If we don't have a write-buffer, ensure that we have one. */
if (util::GetReference(m_write_buffer) == nullptr) {
if (const auto len = std::strlen(m_str); len > 0) {
R_TRY(this->Preallocate(len));
util::Strlcpy<char>(util::GetReference(m_write_buffer).get(), m_str, len + 1);
}
}
/* Check that it's possible for us to remove a child. */
auto *p = this->GetWriteBuffer();
s32 len = std::strlen(p);
R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), fs::ResultNotImplemented());
/* Handle a trailing separator. */
if (len > 0 && (p[len - 1] == '\\' || p[len - 1] == '/')) {
--len;
}
/* Remove the child path segment. */
while ((--len) >= 0 && p[len]) {
if (p[len] == '/' || p[len] == '\\') {
if (len > 0) {
p[len] = 0;
} else {
p[1] = 0;
len = 1;
}
break;
}
}
/* Check that length remains > 0. */
R_UNLESS(len > 0, fs::ResultNotImplemented());
R_SUCCEED();
}
Result Normalize(const PathFlags &flags) {
/* If we're already normalized, nothing to do. */
R_SUCCEED_IF(m_is_normalized);
/* Check if we're normalized. */
bool normalized;
size_t dummy;
R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str, flags));
/* If we're not normalized, normalize. */
if (!normalized) {
/* Determine necessary buffer length. */
auto len = m_write_buffer_length;
if (flags.IsRelativePathAllowed() && fs::IsPathRelative(m_str)) {
len += 2;
}
if (flags.IsWindowsPathAllowed() && fs::IsWindowsPath(m_str, true)) {
len += 1;
}
/* Allocate a new buffer. */
const size_t size = util::AlignUp(len, WriteBufferAlignmentLength);
auto buf = fs::impl::MakeUnique<char[]>(size);
R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInMakeUnique());
/* Normalize into it. */
R_TRY(PathFormatter::Normalize(buf.get(), size, util::GetReference(m_write_buffer).get(), m_write_buffer_length, flags));
/* Set the normalized buffer as our buffer. */
this->SetModifiableBuffer(std::move(buf), size);
}
/* Set normalized. */
m_is_normalized = true;
R_SUCCEED();
}
private:
void ClearBuffer() {
util::GetReference(m_write_buffer).reset();
m_write_buffer_length = 0;
m_str = EmptyPath;
}
void SetModifiableBuffer(WriteBuffer &&buffer, size_t size) {
/* Check pre-conditions. */
AMS_ASSERT(buffer.get() != nullptr);
AMS_ASSERT(size > 0);
AMS_ASSERT(util::IsAligned(size, WriteBufferAlignmentLength));
/* Set write buffer. */
util::GetReference(m_write_buffer) = std::move(buffer);
m_write_buffer_length = size;
m_str = util::GetReference(m_write_buffer).get();
}
constexpr void SetReadOnlyBuffer(const char *buffer) {
m_str = buffer;
if (!std::is_constant_evaluated()) {
util::GetReference(m_write_buffer) = nullptr;
m_write_buffer_length = 0;
}
}
Result Preallocate(size_t length) {
/* Allocate additional space, if needed. */
if (length > m_write_buffer_length) {
/* Allocate buffer. */
const size_t size = util::AlignUp(length, WriteBufferAlignmentLength);
auto buf = fs::impl::MakeUnique<char[]>(size);
R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInMakeUnique());
/* Set write buffer. */
this->SetModifiableBuffer(std::move(buf), size);
}
R_SUCCEED();
}
Result InitializeImpl(const char *path, size_t size) {
if (size > 0 && path[0]) {
/* Pre allocate a buffer for the path. */
R_TRY(this->Preallocate(size + 1));
/* Copy the path. */
const size_t copied = util::Strlcpy<char>(this->GetWriteBuffer(), path, size + 1);
R_UNLESS(copied >= size, fs::ResultUnexpectedInPathA());
} else {
/* We can just clear the buffer. */
this->ClearBuffer();
}
R_SUCCEED();
}
char *GetWriteBuffer() {
AMS_ASSERT(util::GetReference(m_write_buffer) != nullptr);
return util::GetReference(m_write_buffer).get();
}
size_t GetWriteBufferLength() const {
return m_write_buffer_length;
}
public:
ALWAYS_INLINE bool operator==(const fs::Path &rhs) const { return std::strcmp(this->GetString(), rhs.GetString()) == 0; }
ALWAYS_INLINE bool operator!=(const fs::Path &rhs) const { return !(*this == rhs); }
ALWAYS_INLINE bool operator==(const char *p) const { return std::strcmp(this->GetString(), p) == 0; }
ALWAYS_INLINE bool operator!=(const char *p) const { return !(*this == p); }
};
consteval fs::Path MakeConstantPath(const char *s) { return fs::Path(s, util::ConstantInitializeTag{}); }
inline Result SetUpFixedPath(fs::Path *out, const char *s) {
/* Verify the path is normalized. */
bool normalized;
size_t dummy;
R_TRY(PathNormalizer::IsNormalized(std::addressof(normalized), std::addressof(dummy), s));
R_UNLESS(normalized, fs::ResultInvalidPathFormat());
/* Set the fixed path. */
R_RETURN(out->SetShallowBuffer(s));
}
inline Result SetUpFixedPathSingleEntry(fs::Path *out, char *buf, size_t buf_size, const char *e) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%s", e);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathDoubleEntry(fs::Path *out, char *buf, size_t buf_size, const char *e, const char *e2) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%s/%s", e, e2);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveId(fs::Path *out, char *buf, size_t buf_size, u64 id) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%016" PRIx64 "", id);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveMetaName(fs::Path *out, char *buf, size_t buf_size, u32 type) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/%08" PRIx32 ".meta", type);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
inline Result SetUpFixedPathSaveMetaDir(fs::Path *out, char *buf, size_t buf_size, u64 id) {
/* Print the path into the buffer. */
const size_t len = util::TSNPrintf(buf, buf_size, "/saveMeta/%016" PRIx64 "", id);
R_UNLESS(len < buf_size, fs::ResultInvalidArgument());
/* Set up the path. */
R_RETURN(SetUpFixedPath(out, buf));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fssrv/sf/fssrv_sf_path.hpp>
namespace ams::fs {
namespace StringTraits {
constexpr inline char DirectorySeparator = '/';
constexpr inline char DriveSeparator = ':';
constexpr inline char Dot = '.';
constexpr inline char NullTerminator = '\x00';
constexpr inline char AlternateDirectorySeparator = '\\';
}
/* Windows path utilities. */
constexpr inline bool IsWindowsDrive(const char *path) {
AMS_ASSERT(path != nullptr);
const char c = path[0];
return (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) && path[1] == StringTraits::DriveSeparator;
}
constexpr inline bool IsUnc(const char *path) {
return (path[0] == StringTraits::DirectorySeparator && path[1] == StringTraits::DirectorySeparator) ||
(path[0] == StringTraits::AlternateDirectorySeparator && path[1] == StringTraits::AlternateDirectorySeparator);
}
constexpr inline s64 GetWindowsPathSkipLength(const char *path) {
if (IsWindowsDrive(path)) {
return 2;
}
if (IsUnc(path)) {
for (s64 i = 2; path[i] != StringTraits::NullTerminator; ++i) {
if (path[i] == '$' || path[i] == ':') {
return i + 1;
}
}
}
return 0;
}
/* Path utilities. */
inline void Replace(char *dst, size_t dst_size, char old_char, char new_char) {
AMS_ASSERT(dst != nullptr);
for (char *cur = dst; cur < dst + dst_size && *cur != StringTraits::NullTerminator; ++cur) {
if (*cur == old_char) {
*cur = new_char;
}
}
}
Result FspPathPrintf(fssrv::sf::FspPath *dst, const char *format, ...) __attribute__((format(printf, 2, 3)));
inline Result FspPathPrintf(fssrv::sf::FspPath *dst, const char *format, ...) {
AMS_ASSERT(dst != nullptr);
/* Format the path. */
std::va_list va_list;
va_start(va_list, format);
const size_t len = util::VSNPrintf(dst->str, sizeof(dst->str), format, va_list);
va_end(va_list);
/* Validate length. */
R_UNLESS(len < sizeof(dst->str), fs::ResultTooLongPath());
/* Fix slashes. */
Replace(dst->str, sizeof(dst->str) - 1, '\\', '/');
return ResultSuccess();
}
Result VerifyPath(const char *path, int max_path_len, int max_name_len);
bool IsSubPath(const char *lhs, const char *rhs);
/* Path normalization. */
class PathNormalizer {
public:
static constexpr const char RootPath[] = "/";
public:
static constexpr inline bool IsSeparator(char c) {
return c == StringTraits::DirectorySeparator;
}
static constexpr inline bool IsAnySeparator(char c) {
return c == StringTraits::DirectorySeparator || c == StringTraits::AlternateDirectorySeparator;
}
static constexpr inline bool IsNullTerminator(char c) {
return c == StringTraits::NullTerminator;
}
static constexpr inline bool IsCurrentDirectory(const char *p) {
return p[0] == StringTraits::Dot && (IsSeparator(p[1]) || IsNullTerminator(p[1]));
}
static constexpr inline bool IsParentDirectory(const char *p) {
return p[0] == StringTraits::Dot && p[1] == StringTraits::Dot && (IsSeparator(p[2]) || IsNullTerminator(p[2]));
}
static Result Normalize(char *out, size_t *out_len, const char *src, size_t max_out_size, bool unc_preserved = false, bool has_mount_name = false);
static Result IsNormalized(bool *out, const char *path, bool unc_preserved = false, bool has_mount_name = false);
};
}

View File

@ -38,7 +38,10 @@ namespace ams::fs {
static_assert(util::is_pod<QueryRangeInfo>::value);
static_assert(sizeof(QueryRangeInfo) == 0x40);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(QueryRangeInfo) == sizeof(::FsRangeInfo));
#endif
using FileQueryRangeInfo = QueryRangeInfo;
using StorageQueryRangeInfo = QueryRangeInfo;

View File

@ -30,7 +30,7 @@ namespace ams::fs {
private:
std::unique_ptr<fsa::IFile> m_base_file;
public:
explicit ReadOnlyFile(std::unique_ptr<fsa::IFile> &&f) : m_base_file(std::move(f)) { /* ... */ }
explicit ReadOnlyFile(std::unique_ptr<fsa::IFile> &&f) : m_base_file(std::move(f)) { AMS_ASSERT(m_base_file != nullptr); }
virtual ~ReadOnlyFile() { /* ... */ }
private:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final {
@ -46,12 +46,17 @@ namespace ams::fs {
}
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
AMS_UNUSED(offset, buffer, size, option);
bool need_append;
R_TRY(this->DryWrite(std::addressof(need_append), offset, size, option, fs::OpenMode_Read));
AMS_ASSERT(!need_append);
AMS_UNUSED(buffer);
return fs::ResultUnsupportedOperationInReadOnlyFileA();
}
virtual Result DoSetSize(s64 size) override final {
AMS_UNUSED(size);
R_TRY(this->DrySetSize(size, fs::OpenMode_Read));
return fs::ResultUnsupportedOperationInReadOnlyFileA();
}
@ -82,7 +87,7 @@ namespace ams::fs {
explicit ReadOnlyFileSystemTemplate(T &&fs) : m_base_fs(std::move(fs)) { /* ... */ }
virtual ~ReadOnlyFileSystemTemplate() { /* ... */ }
private:
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const fs::Path &path, OpenMode mode) override final {
/* Only allow opening files with mode = read. */
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
@ -96,11 +101,11 @@ namespace ams::fs {
return ResultSuccess();
}
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) override final {
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) override final {
return m_base_fs->OpenDirectory(out_dir, path, mode);
}
virtual Result DoGetEntryType(DirectoryEntryType *out, const char *path) override final {
virtual Result DoGetEntryType(DirectoryEntryType *out, const fs::Path &path) override final {
return m_base_fs->GetEntryType(out, path);
}
@ -108,52 +113,52 @@ namespace ams::fs {
return ResultSuccess();
}
virtual Result DoCreateFile(const char *path, s64 size, int flags) override final {
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override final {
AMS_UNUSED(path, size, flags);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoDeleteFile(const char *path) override final {
virtual Result DoDeleteFile(const fs::Path &path) override final {
AMS_UNUSED(path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoCreateDirectory(const char *path) override final {
virtual Result DoCreateDirectory(const fs::Path &path) override final {
AMS_UNUSED(path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoDeleteDirectory(const char *path) override final {
virtual Result DoDeleteDirectory(const fs::Path &path) override final {
AMS_UNUSED(path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoDeleteDirectoryRecursively(const char *path) override final {
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override final {
AMS_UNUSED(path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoRenameFile(const char *old_path, const char *new_path) override final {
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override final {
AMS_UNUSED(old_path, new_path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override final {
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override final {
AMS_UNUSED(old_path, new_path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoCleanDirectoryRecursively(const char *path) override final {
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override final {
AMS_UNUSED(path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateA();
}
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override final {
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override final {
AMS_UNUSED(out, path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateB();
}
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) override final {
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override final {
AMS_UNUSED(out, path);
return fs::ResultUnsupportedOperationInReadOnlyFileSystemTemplateB();
}

View File

@ -20,11 +20,13 @@
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/fs_query_range.hpp>
#include <stratosphere/fs/fs_path_utils.hpp>
namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteFile : public fsa::IFile, public impl::Newable {
NON_COPYABLE(RemoteFile);
NON_MOVEABLE(RemoteFile);
private:
::FsFile m_base_file;
public:
@ -67,6 +69,8 @@ namespace ams::fs {
};
class RemoteDirectory : public fsa::IDirectory, public impl::Newable {
NON_COPYABLE(RemoteDirectory);
NON_MOVEABLE(RemoteDirectory);
private:
::FsDir m_base_dir;
public:
@ -75,7 +79,8 @@ namespace ams::fs {
virtual ~RemoteDirectory() { fsDirClose(std::addressof(m_base_dir)); }
public:
virtual Result DoRead(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) override final {
return fsDirRead(std::addressof(m_base_dir), out_count, max_entries, out_entries);
static_assert(sizeof(*out_entries) == sizeof(::FsDirectoryEntry));
return fsDirRead(std::addressof(m_base_dir), out_count, max_entries, reinterpret_cast<::FsDirectoryEntry *>(out_entries));
}
virtual Result DoGetEntryCount(s64 *out) override final {
@ -88,6 +93,8 @@ namespace ams::fs {
};
class RemoteFileSystem : public fsa::IFileSystem, public impl::Newable {
NON_COPYABLE(RemoteFileSystem);
NON_MOVEABLE(RemoteFileSystem);
private:
::FsFileSystem m_base_fs;
public:
@ -95,52 +102,51 @@ namespace ams::fs {
virtual ~RemoteFileSystem() { fsFsClose(std::addressof(m_base_fs)); }
private:
Result GetPathForServiceObject(fssrv::sf::Path *out_path, const char *path) {
/* Copy and null terminate. */
std::strncpy(out_path->str, path, sizeof(out_path->str) - 1);
out_path->str[sizeof(out_path->str) - 1] = '\x00';
Result GetPathForServiceObject(fssrv::sf::Path *out_path, const fs::Path &path) {
/* Copy, ensuring length is in bounds. */
const size_t len = util::Strlcpy<char>(out_path->str, path.GetString(), sizeof(out_path->str));
R_UNLESS(len < sizeof(out_path->str), fs::ResultTooLongPath());
/* Replace directory separators. */
fs::Replace(out_path->str, sizeof(out_path->str) - 1, StringTraits::AlternateDirectorySeparator, StringTraits::DirectorySeparator);
/* TODO: Is this still necessary? We originally had it to not break things on low firmware. */
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
fs::Replace(out_path->str, sizeof(out_path->str) - 1, '\\', '/');
#endif
/* Get lengths. */
const auto skip_len = fs::GetWindowsPathSkipLength(path);
const auto rel_path = out_path->str + skip_len;
const auto max_len = fs::EntryNameLengthMax - skip_len;
return VerifyPath(rel_path, max_len, max_len);
R_SUCCEED();
}
public:
virtual Result DoCreateFile(const char *path, s64 size, int flags) override final {
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsCreateFile(std::addressof(m_base_fs), sf_path.str, size, flags);
}
virtual Result DoDeleteFile(const char *path) override final {
virtual Result DoDeleteFile(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsDeleteFile(std::addressof(m_base_fs), sf_path.str);
}
virtual Result DoCreateDirectory(const char *path) override final {
virtual Result DoCreateDirectory(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsCreateDirectory(std::addressof(m_base_fs), sf_path.str);
}
virtual Result DoDeleteDirectory(const char *path) override final {
virtual Result DoDeleteDirectory(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsDeleteDirectory(std::addressof(m_base_fs), sf_path.str);
}
virtual Result DoDeleteDirectoryRecursively(const char *path) override final {
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsDeleteDirectoryRecursively(std::addressof(m_base_fs), sf_path.str);
}
virtual Result DoRenameFile(const char *old_path, const char *new_path) override final {
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override final {
fssrv::sf::Path old_sf_path;
fssrv::sf::Path new_sf_path;
R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
@ -148,7 +154,7 @@ namespace ams::fs {
return fsFsRenameFile(std::addressof(m_base_fs), old_sf_path.str, new_sf_path.str);
}
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override final {
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override final {
fssrv::sf::Path old_sf_path;
fssrv::sf::Path new_sf_path;
R_TRY(GetPathForServiceObject(std::addressof(old_sf_path), old_path));
@ -156,7 +162,7 @@ namespace ams::fs {
return fsFsRenameDirectory(std::addressof(m_base_fs), old_sf_path.str, new_sf_path.str);
}
virtual Result DoGetEntryType(DirectoryEntryType *out, const char *path) override final {
virtual Result DoGetEntryType(DirectoryEntryType *out, const fs::Path &path) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
@ -164,7 +170,7 @@ namespace ams::fs {
return fsFsGetEntryType(std::addressof(m_base_fs), sf_path.str, reinterpret_cast<::FsDirEntryType *>(out));
}
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const fs::Path &path, OpenMode mode) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
@ -178,7 +184,7 @@ namespace ams::fs {
return ResultSuccess();
}
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) override final {
virtual Result DoOpenDirectory(std::unique_ptr<fsa::IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) override final {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
@ -196,37 +202,37 @@ namespace ams::fs {
return fsFsCommit(std::addressof(m_base_fs));
}
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) {
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsGetFreeSpace(std::addressof(m_base_fs), sf_path.str, out);
}
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) {
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsGetTotalSpace(std::addressof(m_base_fs), sf_path.str, out);
}
virtual Result DoCleanDirectoryRecursively(const char *path) {
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsCleanDirectoryRecursively(std::addressof(m_base_fs), sf_path.str);
}
virtual Result DoGetFileTimeStampRaw(FileTimeStampRaw *out, const char *path) {
virtual Result DoGetFileTimeStampRaw(FileTimeStampRaw *out, const fs::Path &path) {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
static_assert(sizeof(FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
return fsFsGetFileTimeStampRaw(std::addressof(m_base_fs), sf_path.str, reinterpret_cast<::FsTimeStampRaw *>(out));
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const char *path) {
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const fs::Path &path) {
fssrv::sf::Path sf_path;
R_TRY(GetPathForServiceObject(std::addressof(sf_path), path));
return fsFsQueryEntry(std::addressof(m_base_fs), dst, dst_size, src, src_size, sf_path.str, static_cast<FsFileSystemQueryId>(query));
}
};
#endif
}

View File

@ -20,35 +20,35 @@
namespace ams::fs {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteStorage : public IStorage, public impl::Newable {
NON_COPYABLE(RemoteStorage);
NON_MOVEABLE(RemoteStorage);
private:
std::unique_ptr<::FsStorage, impl::Deleter> m_base_storage;
::FsStorage m_base_storage;
public:
RemoteStorage(::FsStorage &s) {
m_base_storage = impl::MakeUnique<::FsStorage>();
*m_base_storage = s;
}
RemoteStorage(::FsStorage &s) : m_base_storage(s) { /* ... */}
virtual ~RemoteStorage() { fsStorageClose(m_base_storage.get()); }
virtual ~RemoteStorage() { fsStorageClose(std::addressof(m_base_storage)); }
public:
virtual Result Read(s64 offset, void *buffer, size_t size) override {
return fsStorageRead(m_base_storage.get(), offset, buffer, size);
return fsStorageRead(std::addressof(m_base_storage), offset, buffer, size);
};
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
return fsStorageWrite(m_base_storage.get(), offset, buffer, size);
return fsStorageWrite(std::addressof(m_base_storage), offset, buffer, size);
};
virtual Result Flush() override {
return fsStorageFlush(m_base_storage.get());
return fsStorageFlush(std::addressof(m_base_storage));
};
virtual Result GetSize(s64 *out_size) override {
return fsStorageGetSize(m_base_storage.get(), out_size);
return fsStorageGetSize(std::addressof(m_base_storage), out_size);
};
virtual Result SetSize(s64 size) override {
return fsStorageSetSize(m_base_storage.get(), size);
return fsStorageSetSize(std::addressof(m_base_storage), size);
};
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
@ -57,5 +57,6 @@ namespace ams::fs {
return fs::ResultUnsupportedOperation();
};
};
#endif
}

View File

@ -51,20 +51,20 @@ namespace ams::fs {
RomFileTable *GetRomFileTable();
Result GetFileBaseOffset(s64 *out, const char *path);
public:
virtual Result DoCreateFile(const char *path, s64 size, int flags) override;
virtual Result DoDeleteFile(const char *path) override;
virtual Result DoCreateDirectory(const char *path) override;
virtual Result DoDeleteDirectory(const char *path) override;
virtual Result DoDeleteDirectoryRecursively(const char *path) override;
virtual Result DoRenameFile(const char *old_path, const char *new_path) override;
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) override;
virtual Result DoCleanDirectoryRecursively(const char *path) override;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;

View File

@ -82,6 +82,20 @@ namespace ams::fs {
SaveDataFlags_NeedsSecureDelete = (1 << 3),
};
enum class SaveDataMetaType : u8 {
None = 0,
Thumbnail = 1,
ExtensionContext = 2,
};
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
u8 reserved[0xB];
};
static_assert(util::is_pod<SaveDataMetaInfo>::value);
static_assert(sizeof(SaveDataMetaInfo) == 0x10);
struct SaveDataCreationInfo {
s64 size;
s64 journal_size;

View File

@ -20,6 +20,12 @@ namespace ams::fs {
class IEventNotifier;
struct EncryptionSeed {
char value[0x10];
};
static_assert(util::is_pod<EncryptionSeed>::value);
static_assert(sizeof(EncryptionSeed) == 0x10);
Result MountSdCard(const char *name);
Result MountSdCardErrorReportDirectoryForAtmosphere(const char *name);

View File

@ -30,20 +30,20 @@ namespace ams::fs {
public:
SharedFileSystemHolder(std::shared_ptr<fsa::IFileSystem> f) : m_fs(std::move(f)) { /* ... */ }
public:
virtual Result DoCreateFile(const char *path, s64 size, int flags) override { return m_fs->CreateFile(path, size, flags); }
virtual Result DoDeleteFile(const char *path) override { return m_fs->DeleteFile(path); }
virtual Result DoCreateDirectory(const char *path) override { return m_fs->CreateDirectory(path); }
virtual Result DoDeleteDirectory(const char *path) override { return m_fs->DeleteDirectory(path); }
virtual Result DoDeleteDirectoryRecursively(const char *path) override { return m_fs->DeleteDirectoryRecursively(path); }
virtual Result DoRenameFile(const char *old_path, const char *new_path) override { return m_fs->RenameFile(old_path, new_path); }
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override { return m_fs->RenameDirectory(old_path, new_path); }
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) override { return m_fs->GetEntryType(out, path); }
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override { return m_fs->OpenFile(out_file, path, mode); }
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override { return m_fs->OpenDirectory(out_dir, path, mode); }
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override { return m_fs->CreateFile(path, size, flags); }
virtual Result DoDeleteFile(const fs::Path &path) override { return m_fs->DeleteFile(path); }
virtual Result DoCreateDirectory(const fs::Path &path) override { return m_fs->CreateDirectory(path); }
virtual Result DoDeleteDirectory(const fs::Path &path) override { return m_fs->DeleteDirectory(path); }
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override { return m_fs->DeleteDirectoryRecursively(path); }
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override { return m_fs->RenameFile(old_path, new_path); }
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override { return m_fs->RenameDirectory(old_path, new_path); }
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override { return m_fs->GetEntryType(out, path); }
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override { return m_fs->OpenFile(out_file, path, mode); }
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override { return m_fs->OpenDirectory(out_dir, path, mode); }
virtual Result DoCommit() override { return m_fs->Commit(); }
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override { return m_fs->GetFreeSpaceSize(out, path); }
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) override { return m_fs->GetTotalSpaceSize(out, path); }
virtual Result DoCleanDirectoryRecursively(const char *path) override { return m_fs->CleanDirectoryRecursively(path); }
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override { return m_fs->GetFreeSpaceSize(out, path); }
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override { return m_fs->GetTotalSpaceSize(out, path); }
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override { return m_fs->CleanDirectoryRecursively(path); }
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override { return m_fs->CommitProvisionally(counter); }

View File

@ -31,13 +31,13 @@ namespace ams::fs::fsa {
return ResultSuccess();
}
R_UNLESS(out_entries != nullptr, fs::ResultNullptrArgument());
R_UNLESS(max_entries > 0, fs::ResultInvalidArgument());
return this->DoRead(out_count, out_entries, max_entries);
R_UNLESS(max_entries > 0, fs::ResultInvalidArgument());
R_RETURN(this->DoRead(out_count, out_entries, max_entries));
}
Result GetEntryCount(s64 *out) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetEntryCount(out);
R_RETURN(this->DoGetEntryCount(out));
}
public:
/* TODO: This is a hack to allow the mitm API to work. Find a better way? */

View File

@ -26,58 +26,69 @@ namespace ams::fs::fsa {
virtual ~IFile() { /* ... */ }
Result Read(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
/* Check that we have an output pointer. */
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
/* If we have nothing to read, just succeed. */
if (size == 0) {
*out = 0;
return ResultSuccess();
R_SUCCEED();
}
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
/* Check that the read is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
R_UNLESS(util::IsIntValueRepresentable<s64>(size), fs::ResultOutOfRange());
const s64 signed_size = static_cast<s64>(size);
R_UNLESS(signed_size >= 0, fs::ResultOutOfRange());
R_UNLESS((std::numeric_limits<s64>::max() - offset) >= signed_size, fs::ResultOutOfRange());
return this->DoRead(out, offset, buffer, size, option);
/* Do the read. */
R_RETURN(this->DoRead(out, offset, buffer, size, option));
}
Result Read(size_t *out, s64 offset, void *buffer, size_t size) {
return this->Read(out, offset, buffer, size, ReadOption::None);
}
ALWAYS_INLINE Result Read(size_t *out, s64 offset, void *buffer, size_t size) { R_RETURN(this->Read(out, offset, buffer, size, ReadOption::None)); }
Result GetSize(s64 *out) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetSize(out);
R_RETURN(this->DoGetSize(out));
}
Result Flush() {
return this->DoFlush();
R_RETURN(this->DoFlush());
}
Result Write(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
/* Handle the zero-size case. */
if (size == 0) {
if (option.HasFlushFlag()) {
R_TRY(this->Flush());
}
return ResultSuccess();
R_SUCCEED();
}
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
/* Check the write is valid. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
R_UNLESS(util::IsIntValueRepresentable<s64>(size), fs::ResultOutOfRange());
const s64 signed_size = static_cast<s64>(size);
R_UNLESS(signed_size >= 0, fs::ResultOutOfRange());
R_UNLESS((std::numeric_limits<s64>::max() - offset) >= signed_size, fs::ResultOutOfRange());
return this->DoWrite(offset, buffer, size, option);
R_RETURN(this->DoWrite(offset, buffer, size, option));
}
Result SetSize(s64 size) {
R_UNLESS(size >= 0, fs::ResultOutOfRange());
return this->DoSetSize(size);
R_RETURN(this->DoSetSize(size));
}
Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
return this->DoOperateRange(dst, dst_size, op_id, offset, size, src, src_size);
R_RETURN(this->DoOperateRange(dst, dst_size, op_id, offset, size, src, src_size));
}
Result OperateRange(fs::OperationId op_id, s64 offset, s64 size) {
return this->DoOperateRange(nullptr, 0, op_id, offset, size, nullptr, 0);
R_RETURN(this->DoOperateRange(nullptr, 0, op_id, offset, size, nullptr, 0));
}
public:
/* TODO: This is a hack to allow the mitm API to work. Find a better way? */
@ -91,21 +102,19 @@ namespace ams::fs::fsa {
/* Get the file size, and validate our offset. */
s64 file_size = 0;
R_TRY(this->GetSize(&file_size));
R_TRY(this->DoGetSize(std::addressof(file_size)));
R_UNLESS(offset <= file_size, fs::ResultOutOfRange());
*out = static_cast<size_t>(std::min(file_size - offset, static_cast<s64>(size)));
return ResultSuccess();
R_SUCCEED();
}
Result DrySetSize(s64 size, fs::OpenMode open_mode) {
/* Check that we can write. */
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
AMS_ASSERT(size >= 0);
AMS_UNUSED(size);
return ResultSuccess();
/* Check that we can write. */
R_UNLESS((open_mode & OpenMode_Write) != 0, fs::ResultWriteNotPermitted());
R_SUCCEED();
}
Result DryWrite(bool *out_append, s64 offset, size_t size, const fs::WriteOption &option, fs::OpenMode open_mode) {
@ -116,17 +125,16 @@ namespace ams::fs::fsa {
/* Get the file size. */
s64 file_size = 0;
R_TRY(this->GetSize(&file_size));
R_TRY(this->DoGetSize(&file_size));
/* Determine if we need to append. */
if (file_size < offset + static_cast<s64>(size)) {
*out_append = false;
if (file_size < offset + static_cast<s64>(size)) {
R_UNLESS((open_mode & OpenMode_AllowAppend) != 0, fs::ResultFileExtensionWithoutOpenModeAllowAppend());
*out_append = true;
} else {
*out_append = false;
}
return ResultSuccess();
R_SUCCEED();
}
private:
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) = 0;

View File

@ -18,6 +18,7 @@
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/fs/fs_filesystem_for_debug.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fs::fsa {
@ -26,172 +27,156 @@ namespace ams::fs::fsa {
enum class QueryId {
SetConcatenationFileAttribute = 0,
UpdateMac = 1,
IsSignedSystemPartitionOnSdCardValid = 2,
QueryUnpreparedFileInformation = 3,
};
class IFileSystem {
public:
virtual ~IFileSystem() { /* ... */ }
Result CreateFile(const char *path, s64 size, int option) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
R_UNLESS(size >= 0, fs::ResultOutOfRange());
return this->DoCreateFile(path, size, option);
Result CreateFile(const fs::Path &path, s64 size, int option) {
R_UNLESS(size >= 0, fs::ResultOutOfRange());
R_RETURN(this->DoCreateFile(path, size, option));
}
Result CreateFile(const char *path, s64 size) {
return this->CreateFile(path, size, 0);
Result CreateFile(const fs::Path &path, s64 size) {
R_RETURN(this->CreateFile(path, size, fs::CreateOption_None));
}
Result DeleteFile(const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoDeleteFile(path);
Result DeleteFile(const fs::Path &path) {
R_RETURN(this->DoDeleteFile(path));
}
Result CreateDirectory(const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoCreateDirectory(path);
Result CreateDirectory(const fs::Path &path) {
R_RETURN(this->DoCreateDirectory(path));
}
Result DeleteDirectory(const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoDeleteDirectory(path);
Result DeleteDirectory(const fs::Path &path) {
R_RETURN(this->DoDeleteDirectory(path));
}
Result DeleteDirectoryRecursively(const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoDeleteDirectoryRecursively(path);
Result DeleteDirectoryRecursively(const fs::Path &path) {
R_RETURN(this->DoDeleteDirectoryRecursively(path));
}
Result RenameFile(const char *old_path, const char *new_path) {
R_UNLESS(old_path != nullptr, fs::ResultInvalidPath());
R_UNLESS(new_path != nullptr, fs::ResultInvalidPath());
return this->DoRenameFile(old_path, new_path);
Result RenameFile(const fs::Path &old_path, const fs::Path &new_path) {
R_RETURN(this->DoRenameFile(old_path, new_path));
}
Result RenameDirectory(const char *old_path, const char *new_path) {
R_UNLESS(old_path != nullptr, fs::ResultInvalidPath());
R_UNLESS(new_path != nullptr, fs::ResultInvalidPath());
return this->DoRenameDirectory(old_path, new_path);
Result RenameDirectory(const fs::Path &old_path, const fs::Path &new_path) {
R_RETURN(this->DoRenameDirectory(old_path, new_path));
}
Result GetEntryType(DirectoryEntryType *out, const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetEntryType(out, path);
Result GetEntryType(DirectoryEntryType *out, const fs::Path &path) {
R_RETURN(this->DoGetEntryType(out, path));
}
Result OpenFile(std::unique_ptr<IFile> *out_file, const char *path, OpenMode mode) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
Result OpenFile(std::unique_ptr<IFile> *out_file, const fs::Path &path, OpenMode mode) {
R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument());
R_UNLESS((mode & OpenMode_ReadWrite) != 0, fs::ResultInvalidOpenMode());
R_UNLESS((mode & ~OpenMode_All) == 0, fs::ResultInvalidOpenMode());
return this->DoOpenFile(out_file, path, mode);
R_RETURN(this->DoOpenFile(out_file, path, mode));
}
Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const char *path, OpenDirectoryMode mode) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
Result OpenDirectory(std::unique_ptr<IDirectory> *out_dir, const fs::Path &path, OpenDirectoryMode mode) {
R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument());
R_UNLESS((mode & OpenDirectoryMode_All) != 0, fs::ResultInvalidOpenMode());
R_UNLESS((mode & ~(OpenDirectoryMode_All | OpenDirectoryMode_NotRequireFileSize)) == 0, fs::ResultInvalidOpenMode());
return this->DoOpenDirectory(out_dir, path, mode);
R_RETURN(this->DoOpenDirectory(out_dir, path, mode));
}
Result Commit() {
return this->DoCommit();
R_RETURN(this->DoCommit());
}
Result GetFreeSpaceSize(s64 *out, const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
Result GetFreeSpaceSize(s64 *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetFreeSpaceSize(out, path);
R_RETURN(this->DoGetFreeSpaceSize(out, path));
}
Result GetTotalSpaceSize(s64 *out, const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
Result GetTotalSpaceSize(s64 *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetTotalSpaceSize(out, path);
R_RETURN(this->DoGetTotalSpaceSize(out, path));
}
Result CleanDirectoryRecursively(const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoCleanDirectoryRecursively(path);
Result CleanDirectoryRecursively(const fs::Path &path) {
R_RETURN(this->DoCleanDirectoryRecursively(path));
}
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const fs::Path &path) {
R_UNLESS(out != nullptr, fs::ResultNullptrArgument());
return this->DoGetFileTimeStampRaw(out, path);
R_RETURN(this->DoGetFileTimeStampRaw(out, path));
}
Result QueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, QueryId query, const char *path) {
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
return this->DoQueryEntry(dst, dst_size, src, src_size, query, path);
Result QueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, QueryId query, const fs::Path &path) {
R_RETURN(this->DoQueryEntry(dst, dst_size, src, src_size, query, path));
}
/* These aren't accessible as commands. */
Result CommitProvisionally(s64 counter) {
return this->DoCommitProvisionally(counter);
R_RETURN(this->DoCommitProvisionally(counter));
}
Result Rollback() {
return this->DoRollback();
R_RETURN(this->DoRollback());
}
Result Flush() {
return this->DoFlush();
R_RETURN(this->DoFlush());
}
protected:
/* ...? */
private:
virtual Result DoCreateFile(const char *path, s64 size, int flags) = 0;
virtual Result DoDeleteFile(const char *path) = 0;
virtual Result DoCreateDirectory(const char *path) = 0;
virtual Result DoDeleteDirectory(const char *path) = 0;
virtual Result DoDeleteDirectoryRecursively(const char *path) = 0;
virtual Result DoRenameFile(const char *old_path, const char *new_path) = 0;
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) = 0;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) = 0;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) = 0;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) = 0;
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) = 0;
virtual Result DoDeleteFile(const fs::Path &path) = 0;
virtual Result DoCreateDirectory(const fs::Path &path) = 0;
virtual Result DoDeleteDirectory(const fs::Path &path) = 0;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) = 0;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) = 0;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) = 0;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) = 0;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) = 0;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) = 0;
virtual Result DoCommit() = 0;
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) {
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) {
AMS_UNUSED(out, path);
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) {
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) {
AMS_UNUSED(out, path);
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoCleanDirectoryRecursively(const char *path) = 0;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) = 0;
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const char *path) {
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) {
AMS_UNUSED(out, path);
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const char *path) {
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) {
AMS_UNUSED(dst, dst_size, src, src_size, query, path);
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) {
AMS_UNUSED(counter);
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoRollback() {
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
virtual Result DoFlush() {
return fs::ResultNotImplemented();
R_THROW(fs::ResultNotImplemented());
}
};

View File

@ -83,6 +83,8 @@ namespace ams::fs::impl {
}
}
static_assert(sizeof(size_t) == sizeof(u64));
}
/* Access log result name. */
@ -91,19 +93,41 @@ namespace ams::fs::impl {
#define AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__VALUE__) ::ams::fs::impl::DereferenceOutValue(__VALUE__, AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME)
/* Access log components. */
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE ", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_SIZE ", read_size: %zu"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE ", offset: %" PRId64 ", size: %zu"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID ", thread_id: %" PRIu64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT ", name: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_COUNT ", entry_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_BUFFER_COUNT ", entry_buffer_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OPEN_MODE ", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH ", path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_SIZE ", path: \"%s\", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_OPEN_MODE ", path: \"%s\", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_RENAME ", path: \"%s\", new_path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DIRECTORY_ENTRY_TYPE ", entry_type: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE ", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_SIZE ", read_size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_SIZE ", read_size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE ", offset: %" PRId64 ", size: %" PRIuZ ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID ", thread_id: %" PRIu64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT ", name: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_COUNT ", entry_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ENTRY_BUFFER_COUNT ", entry_buffer_count: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OPEN_MODE ", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH ", path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_SIZE ", path: \"%s\", size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH_AND_OPEN_MODE ", path: \"%s\", open_mode: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_RENAME ", path: \"%s\", new_path: \"%s\""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DIRECTORY_ENTRY_TYPE ", entry_type: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE ", content_type: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION ", mount_host_option: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH ", root_path: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_APPLICATION_ID ", applicationid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_BIS_PARTITION_ID ", bispartitionid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_STORAGE_ID ", contentstorageid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID ", systemdataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DATA_ID ", dataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_HANDLE ", gamecard_handle: 0x%" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_PARTITION ", gamecard_partition: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_IMAGE_DIRECTORY_ID ", imagedirectoryid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID ", programid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID ", savedataid: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID ", savedataspaceid: %s"
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_OWNER_ID ", save_data_owner_id: 0x%" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID ", userid: 0x%016" PRIx64 "%016" PRIx64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_FLAGS ", save_data_flags: 0x%08" PRIX32 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE ", save_data_journal_size: %" PRId64 ""
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE ", save_data_size: %" PRId64 ""
/* Access log formats. */
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE ""
@ -130,62 +154,135 @@ namespace ams::fs::impl {
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_GET_SPACE_SIZE(__OUT_SIZE__, __NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE, __NAME__, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__OUT_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_APPLICATION_PACKAGE(__NAME__, __PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH, (__NAME__), (__PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_BIS(__NAME__, __ID__, __PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_BIS_PARTITION_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__), (__PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CODE(__NAME__, __PATH__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID, (__NAME__), (__PATH__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH(__NAME__, __PATH__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PROGRAM_ID(__NAME__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__ID__), ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH_AND_PROGRAM_ID(__NAME__, __PATH__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_PROGRAM_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), (__ID__).value, ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_PATH_AND_DATA_ID(__NAME__, __PATH__, __ID__, __TYPE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_TYPE, (__NAME__), (__PATH__), (__ID__).value, ::ams::fs::impl::IdString().ToString(__TYPE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_CONTENT_STORAGE(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_CONTENT_STORAGE_ID, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_DEVICE_SAVE_DATA_APPLICATION_ID(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_APPLICATION_ID, (__NAME__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_GAME_CARD_PARTITION(__NAME__, __GCHANDLE__, __PARTITION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_HANDLE AMS_FS_IMPL_ACCESS_LOG_FORMAT_GAME_CARD_PARTITION, (__NAME__), __GCHANDLE__, ::ams::fs::impl::IdString().ToString(__PARTITION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_ROOT() \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT, (AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_ROOT_WITH_OPTION(__OPTION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION, (AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME), ::ams::fs::impl::IdString().ToString(__OPTION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST(__NAME__, __ROOT_PATH__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH, (__NAME__), (__ROOT_PATH__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_WITH_OPTION(__NAME__, __ROOT_PATH__, __OPTION__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_ROOT_PATH AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_HOST_OPTION, (__NAME__), (__ROOT_PATH__), ::ams::fs::impl::IdString().ToString(__OPTION__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_IMAGE_DIRECTORY(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_IMAGE_DIRECTORY_ID, (__NAME__), ::ams::fs::impl::IdString().ToString(__ID__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_SYSTEM_DATA(__NAME__, __ID__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID, (__NAME__), (__ID__).value
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT_SYSTEM_SAVE_DATA(__NAME__, __SPACE__, __SAVE__, __USER__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_MOUNT AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID, \
(__NAME__), ::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1]
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_CREATE_SYSTEM_SAVE_DATA(__SPACE__, __SAVE__, __USER__, __OWNER__, __SIZE__, __JOURNAL_SIZE__, __FLAGS__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_OWNER_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_FLAGS, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1], (__OWNER__), (__SIZE__), (__JOURNAL_SIZE__), (__FLAGS__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DELETE_SAVE_DATA(__SPACE__, __SAVE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_DELETE_SYSTEM_SAVE_DATA(__SPACE__, __SAVE__, __USER__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_USER_ID, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__USER__).data[0], (__USER__).data[1]
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_EXTEND_SAVE_DATA(__SPACE__, __SAVE__, __SIZE__, __JOURNAL_SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SPACE_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_SIZE AMS_FS_IMPL_ACCESS_LOG_FORMAT_SAVE_DATA_JOURNAL_SIZE, \
::ams::fs::impl::IdString().ToString(__SPACE__), (__SAVE__), (__SIZE__), (__JOURNAL_SIZE__)
#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_MOUNT_SYSTEM_DATA_CACHE_SIZE(__ID__, __SIZE__) \
AMS_FS_IMPL_ACCESS_LOG_FORMAT_SYSTEM_DATA_ID AMS_FS_IMPL_ACCESS_LOG_FORMAT_QUERY_SIZE, (__ID__).value, AMS_FS_IMPL_ACCESS_LOG_DEREFERENCE_OUT_VALUE(__SIZE__)
/* Access log invocation lambdas. */
#define AMS_FS_IMPL_ACCESS_LOG_IMPL(__EXPR__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *name) -> Result { \
if (!(__ENABLED__)) { \
return (__EXPR__); \
} else { \
const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, start, end, name, __HANDLE__, __VA_ARGS__); \
return AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME; \
} \
#define AMS_FS_IMPL_ACCESS_LOG_IMPL(__EXPR__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __fs_start_tick, __fs_end_tick, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_WITH_PRIORITY_IMPL(__EXPR__, __PRIORITY__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *name) -> Result { \
if (!(__ENABLED__)) { \
return (__EXPR__); \
} else { \
const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __PRIORITY__, start, end, name, __HANDLE__, __VA_ARGS__); \
return AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME; \
} \
#define AMS_FS_IMPL_ACCESS_LOG_WITH_PRIORITY_IMPL(__EXPR__, __PRIORITY__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __PRIORITY__, __fs_start_tick, __fs_end_tick, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL(__RESULT__, __START__, __END__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *name) -> Result { \
if (!(__ENABLED__)) { \
return __RESULT__; \
} else { \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__RESULT__); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __START__, __END__, name, __HANDLE__, __VA_ARGS__); \
return AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME; \
} \
#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL(__RESULT__, __START__, __END__, __HANDLE__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__RESULT__); \
} else { \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__RESULT__); \
::ams::fs::impl::OutputAccessLog(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __START__, __END__, __fs_func_name_, __HANDLE__, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL(__EXPR__, __ENABLED__, __NAME__, ...) \
[&](const char *name) -> Result { \
if (!(__ENABLED__)) { \
return (__EXPR__); \
} else { \
const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLogUnlessResultSuccess(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, start, end, name, nullptr, __VA_ARGS__); \
return AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME; \
} \
#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL(__EXPR__, __ENABLED__, __NAME__, ...) \
[&](const char *__fs_func_name_) -> Result { \
if (!(__ENABLED__)) { \
R_RETURN(__EXPR__); \
} else { \
const ::ams::os::Tick __fs_start_tick = ::ams::os::GetSystemTick(); \
const auto AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME = (__EXPR__); \
const ::ams::os::Tick __fs_end_tick = ::ams::os::GetSystemTick(); \
::ams::fs::impl::OutputAccessLogUnlessResultSuccess(AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME, __fs_start_tick, __fs_end_tick, __fs_func_name_, nullptr, __VA_ARGS__); \
R_RETURN( AMS_FS_IMPL_ACCESS_LOG_RESULT_NAME ); \
} \
}(__NAME__)
/* Access log api. */
#define AMS_FS_IMPL_ACCESS_LOG(__EXPR__, __HANDLE__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM(__EXPR__, __HANDLE__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System) && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_WITH_NAME(__EXPR__, __HANDLE__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), __NAME__, __VA_ARGS__)
@ -195,6 +292,37 @@ namespace ams::fs::impl {
#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED(__EXPR__, ...) \
AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL((__EXPR__), ::ams::fs::impl::IsEnabledAccessLog(), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
/* FS Accessor logging. */
#define AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL(__NAME__, __ENABLED__) \
do { \
if (static_cast<bool>(__ENABLED__)) { \
::ams::fs::impl::EnableFileSystemAccessorAccessLog((__NAME__)); \
} \
} while (false)
#define AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE(__NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL((__NAME__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application))
// DEBUG
#define AMS_FS_FORCE_ENABLE_SYSTEM_MOUNT_ACCESS_LOG
/* System access log api. */
#if defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_FS_FORCE_ENABLE_SYSTEM_MOUNT_ACCESS_LOG)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_MOUNT(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_FS_ACCESSOR_ENABLE(__NAME__) \
AMS_FS_IMPL_ACCESS_LOG_FS_ACCESSOR_ENABLE_IMPL((__NAME__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_System))
#else
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_MOUNT(__EXPR__, __NAME__, ...) (__EXPR__)
#define AMS_FS_IMPL_ACCESS_LOG_SYSTEM_FS_ACCESSOR_ENABLE(__NAME__) static_cast<void>(0)
#endif
/* Specific utilities. */
#define AMS_FS_IMPL_ACCESS_LOG_FILESYSTEM(__EXPR__, __HANDLE__, __FILESYSTEM__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && (__FILESYSTEM__)->IsEnabledAccessLog(), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
@ -202,5 +330,11 @@ namespace ams::fs::impl {
#define AMS_FS_IMPL_ACCESS_LOG_FILESYSTEM_WITH_NAME(__EXPR__, __HANDLE__, __FILESYSTEM__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && (__FILESYSTEM__)->IsEnabledAccessLog(), __NAME__, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_MOUNT(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_MOUNT_UNLESS_R_SUCCEEDED(__EXPR__, __NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL((__EXPR__), ::ams::fs::impl::IsEnabledAccessLog(::ams::fs::impl::AccessLogTarget_Application), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)
#define AMS_FS_IMPL_ACCESS_LOG_UNMOUNT(__EXPR__, __MOUNT_NAME__, ...) \
AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), nullptr, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledFileSystemAccessorAccessLog(__MOUNT_NAME__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__)

View File

@ -19,10 +19,17 @@ namespace ams::fs::impl {
/* Delimiting of mount names. */
constexpr inline const char ReservedMountNamePrefixCharacter = '@';
constexpr inline const char * const MountNameDelimiter = ":/";
#define AMS_FS_IMPL_MOUNT_NAME_DELIMITER ":/"
#define AMS_FS_IMPL_MOUNT_NAME_DELIMITER_LEN 2
constexpr inline const char * const MountNameDelimiter = AMS_FS_IMPL_MOUNT_NAME_DELIMITER;
/* Filesystem names. */
constexpr inline const char * const HostRootFileSystemMountName = "@Host";
#define AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME "@Host"
#define AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME_LEN 5
constexpr inline const char * const HostRootFileSystemMountName = AMS_FS_IMPL_HOST_ROOT_FILE_SYSTEM_MOUNT_NAME;
constexpr inline const char * const SdCardFileSystemMountName = "@Sdcard";
constexpr inline const char * const GameCardFileSystemMountName = "@Gc";

View File

@ -27,11 +27,13 @@ namespace ams::fs::impl {
TlsIoPriority_Background = 3,
};
#if defined(ATMOSPHERE_OS_HORIZON)
/* Ensure that TlsIo priority matches libnx priority. */
static_assert(TlsIoPriority_Normal == static_cast<TlsIoPriority>(::FsPriority_Normal));
static_assert(TlsIoPriority_Realtime == static_cast<TlsIoPriority>(::FsPriority_Realtime));
static_assert(TlsIoPriority_Low == static_cast<TlsIoPriority>(::FsPriority_Low));
static_assert(TlsIoPriority_Background == static_cast<TlsIoPriority>(::FsPriority_Background));
#endif
constexpr inline Result ConvertFsPriorityToTlsIoPriority(u8 *out, PriorityRaw priority) {
AMS_ASSERT(out != nullptr);

View File

@ -55,7 +55,7 @@ namespace ams::fs::impl {
({ \
const ::ams::Result __tmp_fs_result = (__RESULT__); \
AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, false); \
return __tmp_fs_result; \
R_THROW(__tmp_fs_result); \
})
#define AMS_FS_R_UNLESS(__EXPR__, __RESULT__) \

View File

@ -20,7 +20,6 @@
#include <stratosphere/fssrv/sf/fssrv_sf_i_event_notifier.hpp>
#include <stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp>
#include <stratosphere/fssrv/fssrv_access_control.hpp>
#include <stratosphere/fssrv/fssrv_path_normalizer.hpp>
#include <stratosphere/fssrv/fssrv_nca_crypto_configuration.hpp>
#include <stratosphere/fssrv/fssrv_memory_resource_from_standard_allocator.hpp>
#include <stratosphere/fssrv/fssrv_memory_resource_from_exp_heap.hpp>
@ -28,8 +27,12 @@
#include <stratosphere/fssrv/fscreator/fssrv_partition_file_system_creator.hpp>
#include <stratosphere/fssrv/fscreator/fssrv_rom_file_system_creator.hpp>
#include <stratosphere/fssrv/fscreator/fssrv_storage_on_nca_creator.hpp>
#include <stratosphere/fssrv/fscreator/fssrv_local_file_system_creator.hpp>
#include <stratosphere/fssrv/fscreator/fssrv_subdirectory_file_system_creator.hpp>
#include <stratosphere/fssrv/fscreator/fssrv_storage_on_nca_creator.hpp>
#include <stratosphere/fssrv/fssrv_file_system_proxy_server_session_resource_manager.hpp>
#include <stratosphere/fssrv/impl/fssrv_file_system_proxy_service_object.hpp>
#include <stratosphere/fssrv/fssrv_file_system_proxy_api.hpp>
#include <stratosphere/fssrv/fssrv_program_registry_impl.hpp>
#include <stratosphere/fssrv/fssrv_program_registry_service.hpp>
#include <stratosphere/fssrv/fssrv_file_system_proxy_api.hpp>
#include <stratosphere/fssrv/fssrv_nca_file_system_service_impl.hpp>

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssrv/fssrv_i_file_system_creator.hpp>
namespace ams::fssrv::fscreator {
class LocalFileSystemCreator final : public ILocalFileSystemCreator {
NON_COPYABLE(LocalFileSystemCreator);
NON_MOVEABLE(LocalFileSystemCreator);
private:
bool m_is_development;
public:
explicit LocalFileSystemCreator(bool dev) : m_is_development(dev) { /* ... */ }
virtual Result Create(std::shared_ptr<fs::fsa::IFileSystem> *out, const fs::Path &path, bool case_sensitive, bool ensure_root, Result on_path_not_found) override;
};
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssrv/fssrv_i_file_system_creator.hpp>
namespace ams::fssrv::fscreator {
class SubDirectoryFileSystemCreator final : public ISubDirectoryFileSystemCreator {
NON_COPYABLE(SubDirectoryFileSystemCreator);
NON_MOVEABLE(SubDirectoryFileSystemCreator);
public:
explicit SubDirectoryFileSystemCreator() { /* ... */ }
virtual Result Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::fsa::IFileSystem> base_fs, const fs::Path &path) override;
};
}

View File

@ -22,15 +22,43 @@ namespace ams::fssrv::fscreator {
}
namespace ams::fssystem {
namespace ams::fssrv {
class IBufferManager;
class BaseStorageServiceImpl;
class BaseFileSystemServiceImpl;
class NcaFileSystemServiceImpl;
class SaveDataFileSystemServiceImpl;
class AccessFailureManagementServiceImpl;
class TimeServiceImpl;
class StatusReportServiceImpl;
class ProgramRegistryServiceImpl;
class AccessLogServiceImpl;
class DebugConfigurationServiceImpl;
struct FileSystemProxyConfiguration {
fscreator::FileSystemCreatorInterfaces *m_fs_creator_interfaces;
BaseStorageServiceImpl *m_base_storage_service_impl;
BaseFileSystemServiceImpl *m_base_file_system_service_impl;
NcaFileSystemServiceImpl *m_nca_file_system_service_impl;
SaveDataFileSystemServiceImpl *m_save_data_file_system_service_impl;
AccessFailureManagementServiceImpl *m_access_failure_management_service_impl;
TimeServiceImpl *m_time_service_impl;
StatusReportServiceImpl *m_status_report_service_impl;
ProgramRegistryServiceImpl *m_program_registry_service_impl;
AccessLogServiceImpl *m_access_log_service_impl;
DebugConfigurationServiceImpl *m_debug_configuration_service_impl;
};
struct InternalProgramIdRangeForSpeedEmulation {
u64 program_id_value_min;
u64 program_id_value_max;
};
}
namespace ams::fssrv {
void InitializeForFileSystemProxy(fscreator::FileSystemCreatorInterfaces *fs_creator_interfaces, fssystem::IBufferManager *buffer_manager, bool is_development_function_enabled);
void InitializeForFileSystemProxy(const FileSystemProxyConfiguration &config);
void InitializeFileSystemProxyServer(int threads);

View File

@ -43,13 +43,106 @@ namespace ams::fssrv {
~FileSystemProxyImpl();
/* TODO */
public:
/* fsp-srv */
Result OpenFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 type);
Result SetCurrentProcess(const ams::sf::ClientProcessId &client_pid);
Result OpenDataFileSystemByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out);
Result OpenFileSystemWithPatch(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 type);
Result OpenFileSystemWithId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u64 program_id, u32 type);
Result OpenDataFileSystemByProgramId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id);
Result OpenBisFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 id);
Result OpenBisStorage(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 id);
Result InvalidateBisCache();
Result OpenHostFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path);
Result OpenSdCardFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out);
Result FormatSdCardFileSystem();
Result DeleteSaveDataFileSystem(u64 save_data_id);
Result CreateSaveDataFileSystem(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info);
Result CreateSaveDataFileSystemBySystemSaveDataId(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info);
Result RegisterSaveDataFileSystemAtomicDeletion(const ams::sf::InBuffer &save_data_ids);
Result DeleteSaveDataFileSystemBySaveDataSpaceId(u8 indexer_space_id, u64 save_data_id);
Result FormatSdCardDryRun();
Result IsExFatSupported(ams::sf::Out<bool> out);
Result DeleteSaveDataFileSystemBySaveDataAttribute(u8 space_id, const fs::SaveDataAttribute &attribute);
Result OpenGameCardStorage(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 handle, u32 partition);
Result OpenGameCardFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 handle, u32 partition);
Result ExtendSaveDataFileSystem(u8 space_id, u64 save_data_id, s64 available_size, s64 journal_size);
Result DeleteCacheStorage(u16 index);
Result GetCacheStorageSize(ams::sf::Out<s64> out_size, ams::sf::Out<s64> out_journal_size, u16 index);
Result CreateSaveDataFileSystemWithHashSalt(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info, const fs::HashSalt &salt);
Result OpenHostFileSystemWithOption(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 option);
Result OpenSaveDataFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute);
Result OpenSaveDataFileSystemBySystemSaveDataId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute);
Result OpenReadOnlySaveDataFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute);
Result ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(const ams::sf::OutBuffer &buffer, u8 space_id, u64 save_data_id);
Result ReadSaveDataFileSystemExtraData(const ams::sf::OutBuffer &buffer, u64 save_data_id);
Result WriteSaveDataFileSystemExtraData(u64 save_data_id, u8 space_id, const ams::sf::InBuffer &buffer);
/* ... */
Result OpenImageDirectoryFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id);
/* ... */
Result OpenContentStorageFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id);
/* ... */
Result OpenDataStorageByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out);
Result OpenDataStorageByProgramId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::ProgramId program_id);
Result OpenDataStorageByDataId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::DataId data_id, u8 storage_id);
Result OpenPatchDataStorageByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out);
Result OpenDataFileSystemWithProgramIndex(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 index);
Result OpenDataStorageWithProgramIndex(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u8 index);
Result OpenDataStorageByPath(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, const fssrv::sf::FspPath &path, u32 type);
Result OpenDeviceOperator(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDeviceOperator>> out);
Result OpenSdCardDetectionEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out);
Result OpenGameCardDetectionEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out);
Result OpenSystemDataUpdateEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out);
Result NotifySystemDataUpdateEvent();
/* ... */
Result SetCurrentPosixTime(s64 posix_time);
/* ... */
Result GetRightsId(ams::sf::Out<fs::RightsId> out, ncm::ProgramId program_id, ncm::StorageId storage_id);
Result RegisterExternalKey(const fs::RightsId &rights_id, const spl::AccessKey &access_key);
Result UnregisterAllExternalKey();
Result GetRightsIdByPath(ams::sf::Out<fs::RightsId> out, const fssrv::sf::FspPath &path);
Result GetRightsIdAndKeyGenerationByPath(ams::sf::Out<fs::RightsId> out, ams::sf::Out<u8> out_key_generation, const fssrv::sf::FspPath &path);
Result SetCurrentPosixTimeWithTimeDifference(s64 posix_time, s32 time_difference);
Result GetFreeSpaceSizeForSaveData(ams::sf::Out<s64> out, u8 space_id);
Result VerifySaveDataFileSystemBySaveDataSpaceId();
Result CorruptSaveDataFileSystemBySaveDataSpaceId();
Result QuerySaveDataInternalStorageTotalSize();
Result GetSaveDataCommitId();
Result UnregisterExternalKey(const fs::RightsId &rights_id);
Result SetSdCardEncryptionSeed(const fs::EncryptionSeed &seed);
Result SetSdCardAccessibility(bool accessible);
Result IsSdCardAccessible(ams::sf::Out<bool> out);
Result IsSignedSystemPartitionOnSdCardValid(ams::sf::Out<bool> out);
Result OpenAccessFailureDetectionEventNotifier();
/* ... */
Result RegisterProgramIndexMapInfo(const ams::sf::InBuffer &buffer, s32 count);
Result SetBisRootForHost(u32 id, const fssrv::sf::FspPath &path);
Result SetSaveDataSize(s64 size, s64 journal_size);
Result SetSaveDataRootPath(const fssrv::sf::FspPath &path);
Result DisableAutoSaveDataCreation();
Result SetGlobalAccessLogMode(u32 mode);
Result GetGlobalAccessLogMode(ams::sf::Out<u32> out);
Result OutputAccessLogToSdCard(const ams::sf::InBuffer &buf);
Result RegisterUpdatePartition();
Result OpenRegisteredUpdatePartition(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out);
/* ... */
Result GetProgramIndexForAccessLog(ams::sf::Out<u32> out_idx, ams::sf::Out<u32> out_count);
Result GetFsStackUsage(ams::sf::Out<u32> out, u32 type);
Result UnsetSaveDataRootPath();
Result OutputMultiProgramTagAccessLog();
Result FlushAccessLogOnSdCard();
Result OutputApplicationInfoAccessLog();
Result RegisterDebugConfiguration(u32 key, s64 value);
Result UnregisterDebugConfiguration(u32 key);
Result OverrideSaveDataTransferTokenSignVerificationKey(const ams::sf::InBuffer &buf);
Result CorruptSaveDataFileSystemByOffset(u8 space_id, u64 save_data_id, s64 offset);
/* ... */
public:
/* fsp-ldr */
Result OpenCodeFileSystemDeprecated(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, const fssrv::sf::Path &path, ncm::ProgramId program_id);
Result OpenCodeFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, ams::sf::Out<fs::CodeVerificationData> out_verif, const fssrv::sf::Path &path, ncm::ProgramId program_id);
Result IsArchivedProgram(ams::sf::Out<bool> out, u64 process_id);
Result SetCurrentProcess(const ams::sf::ClientProcessId &client_pid);
};
static_assert(sf::IsIFileSystemProxy<FileSystemProxyImpl>);
static_assert(sf::IsIFileSystemProxyForLoader<FileSystemProxyImpl>);

View File

@ -22,6 +22,8 @@ namespace ams::fs {
class IStorage;
enum class BisPartitionId;
class Path;
namespace fsa {
class IFileSystem;
@ -67,7 +69,24 @@ namespace ams::fssrv::fscreator {
virtual Result CreateNcaReader(std::shared_ptr<fssystem::NcaReader> *out, std::shared_ptr<fs::IStorage> storage) = 0;
};
class ILocalFileSystemCreator {
public:
virtual Result Create(std::shared_ptr<fs::fsa::IFileSystem> *out, const fs::Path &path, bool case_sensitive, bool ensure_root, Result on_path_not_found) = 0;
public:
Result Create(std::shared_ptr<fs::fsa::IFileSystem> *out, const fs::Path &path, bool case_sensitive) {
R_RETURN(this->Create(out, path, case_sensitive, false, ResultSuccess()));
}
};
class ISubDirectoryFileSystemCreator {
public:
virtual Result Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::fsa::IFileSystem> base_fs, const fs::Path &path) = 0;
};
struct FileSystemCreatorInterfaces {
ILocalFileSystemCreator *local_fs_creator;
ISubDirectoryFileSystemCreator *subdir_fs_creator;
/* TODO: These don't exist any more, and should be refactored out. */
IRomFileSystemCreator *rom_fs_creator;
IPartitionFileSystemCreator *partition_fs_creator;
IStorageOnNcaCreator *storage_on_nca_creator;

View File

@ -34,6 +34,7 @@ namespace ams::fssrv {
size_t m_peak_allocated_size;
public:
explicit MemoryResourceFromStandardAllocator(mem::StandardAllocator *allocator);
constexpr virtual ~MemoryResourceFromStandardAllocator() = default;
public:
size_t GetPeakFreeSize() const { return m_peak_free_size; }
size_t GetCurrentFreeSize() const { return m_current_free_size; }

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fssystem/fssystem_pimpl.hpp>
#include <stratosphere/fssrv/fssrv_file_system_proxy_api.hpp>
namespace ams::fssrv {
class BaseFileSystemServiceImpl;
class ProgramRegistryServiceImpl;
class AccessFailureManagementServiceImpl;
namespace fscreator {
class LocalFileSystemCreator;
class TargetManagerFileSystemCreator;
class PartitionFileSystemCreator;
class IRomFileSystemCreator;
class StorageOnNcaCreator;
class SubDirectoryFileSystemCreator;
class EncryptedFileSystemCreator;
class INspRootFileSystemCreator;
}
namespace impl {
class UpdatePartitionPath;
class ExternalKeyManager;
class LocationResolverSet;
class SystemDataUpdateEventManager;
}
class NcaFileSystemServiceImpl {
public:
struct Configuration {
BaseFileSystemServiceImpl *base_fs_service;
fscreator::LocalFileSystemCreator *local_fs_creator;
fscreator::TargetManagerFileSystemCreator *tm_fs_creator;
fscreator::PartitionFileSystemCreator *partition_fs_creator;
fscreator::IRomFileSystemCreator *rom_fs_creator;
fscreator::StorageOnNcaCreator *storage_on_nca_creator;
fscreator::SubDirectoryFileSystemCreator *subdir_fs_creator;
fscreator::EncryptedFileSystemCreator *encrypted_fs_creator;
fscreator::INspRootFileSystemCreator *nsp_root_fs_creator;
ProgramRegistryServiceImpl *program_registry_service;
AccessFailureManagementServiceImpl *access_failure_management_service;
InternalProgramIdRangeForSpeedEmulation program_id_range_for_speed_emulation;
};
private:
struct MountInfo {
bool is_game_card;
u32 gc_handle;
bool is_host_fs;
bool can_mount_nca;
};
private:
Configuration m_config;
fssystem::Pimpl<impl::UpdatePartitionPath, 0x350> m_update_partition_path;
fssystem::Pimpl<impl::ExternalKeyManager, 0x50> m_external_key_manager;
fssystem::Pimpl<impl::UpdatePartitionPath, 0xA8> m_location_resolver_set;
fssystem::Pimpl<impl::SystemDataUpdateEventManager, 0x48> m_system_data_update_event_manager;
fs::EncryptionSeed m_encryption_seed;
int m_romfs_remount_for_data_corruption_count;
int m_romfs_unrecoverable_data_corruption_by_remount_count;
int m_romfs_recovered_by_invalidate_cache_count;
os::SdkMutex m_romfs_count_mutex;
public:
NcaFileSystemServiceImpl(const Configuration &cfg) : m_config(cfg) { /* ... */ }
};
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
namespace ams::fssrv {
/* This is in fssrv::detail in official code. */
/* TODO: Consider moving to ::impl? */
class PathNormalizer {
public:
enum Option : u32 {
Option_None = BIT(0),
Option_PreserveUnc = BIT(1),
Option_PreserveTailSeparator = BIT(2),
Option_HasMountName = BIT(3),
Option_AcceptEmpty = BIT(4),
};
private:
using Buffer = std::unique_ptr<char[], fs::impl::Deleter>;
private:
Buffer m_buffer;
const char *m_path;
Result m_result;
private:
static Result Normalize(const char **out_path, Buffer *out_buf, const char *path, bool preserve_unc, bool preserve_tail_sep, bool has_mount_name);
public:
/* TODO: Remove non-option constructor. */
explicit PathNormalizer(const char *p) : m_buffer(), m_path(nullptr), m_result(ResultSuccess()) {
m_result = Normalize(std::addressof(m_path), std::addressof(m_buffer), p, false, false, false);
}
PathNormalizer(const char *p, u32 option) : m_buffer(), m_path(nullptr), m_result(ResultSuccess()) {
if ((option & Option_AcceptEmpty) && p[0] == '\x00') {
m_path = p;
} else {
const bool preserve_unc = (option & Option_PreserveUnc);
const bool preserve_tail_sep = (option & Option_PreserveTailSeparator);
const bool has_mount_name = (option & Option_HasMountName);
m_result = Normalize(std::addressof(m_path), std::addressof(m_buffer), p, preserve_unc, preserve_tail_sep, has_mount_name);
}
}
Result GetResult() const {
return m_result;
}
const char *GetPath() const {
return m_path;
}
};
}

View File

@ -39,13 +39,13 @@ namespace ams::fssrv::impl {
class FileInterfaceAdapter {
NON_COPYABLE(FileInterfaceAdapter);
NON_MOVEABLE(FileInterfaceAdapter);
private:
ams::sf::SharedPointer<FileSystemInterfaceAdapter> m_parent_filesystem;
std::unique_ptr<fs::fsa::IFile> m_base_file;
util::unique_lock<fssystem::SemaphoreAdapter> m_open_count_semaphore;
bool m_allow_all_operations;
public:
FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema);
~FileInterfaceAdapter();
FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, bool allow_all);
private:
void InvalidateCache();
public:
@ -62,13 +62,13 @@ namespace ams::fssrv::impl {
class DirectoryInterfaceAdapter {
NON_COPYABLE(DirectoryInterfaceAdapter);
NON_MOVEABLE(DirectoryInterfaceAdapter);
private:
ams::sf::SharedPointer<FileSystemInterfaceAdapter> m_parent_filesystem;
std::unique_ptr<fs::fsa::IDirectory> m_base_dir;
util::unique_lock<fssystem::SemaphoreAdapter> m_open_count_semaphore;
bool m_allow_all_operations;
public:
DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema);
~DirectoryInterfaceAdapter();
DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, bool allow_all);
public:
/* Command API */
Result Read(ams::sf::Out<s64> out, const ams::sf::OutBuffer &out_entries);
@ -78,22 +78,26 @@ namespace ams::fssrv::impl {
class FileSystemInterfaceAdapter : public ams::sf::ISharedObject {
NON_COPYABLE(FileSystemInterfaceAdapter);
NON_MOVEABLE(FileSystemInterfaceAdapter);
private:
std::shared_ptr<fs::fsa::IFileSystem> m_base_fs;
util::unique_lock<fssystem::SemaphoreAdapter> m_mount_count_semaphore;
os::ReaderWriterLock m_invalidation_lock;
bool m_open_count_limited;
bool m_deep_retry_enabled = false;
fs::PathFlags m_path_flags;
bool m_allow_all_operations;
bool m_is_mitm_interface;
public:
FileSystemInterfaceAdapter(std::shared_ptr<fs::fsa::IFileSystem> &&fs, bool open_limited);
/* TODO: Other constructors. */
FileSystemInterfaceAdapter(std::shared_ptr<fs::fsa::IFileSystem> &&fs, const fs::PathFlags &flags, bool allow_all, bool is_mitm_interface = false)
: m_base_fs(std::move(fs)), m_path_flags(flags), m_allow_all_operations(allow_all), m_is_mitm_interface(is_mitm_interface)
{
/* ... */
}
~FileSystemInterfaceAdapter();
public:
bool IsDeepRetryEnabled() const;
bool IsAccessFailureDetectionObserved() const;
util::optional<std::shared_lock<os::ReaderWriterLock>> AcquireCacheInvalidationReadLock();
os::ReaderWriterLock &GetReaderWriterLockForCacheInvalidation();
FileSystemInterfaceAdapter(std::shared_ptr<fs::fsa::IFileSystem> &&fs, bool allow_all, bool is_mitm_interface = false)
: m_base_fs(std::move(fs)), m_path_flags(), m_allow_all_operations(allow_all), m_is_mitm_interface(is_mitm_interface)
{
/* ... */
}
private:
Result SetUpPath(fs::Path *out, const fssrv::sf::Path &sf_path);
public:
/* Command API. */
Result CreateFile(const fssrv::sf::Path &path, s64 size, s32 option);
@ -116,4 +120,143 @@ namespace ams::fssrv::impl {
Result QueryEntry(const ams::sf::OutBuffer &out_buf, const ams::sf::InBuffer &in_buf, s32 query_id, const fssrv::sf::Path &path);
};
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteFile {
NON_COPYABLE(RemoteFile);
NON_MOVEABLE(RemoteFile);
private:
::FsFile m_base_file;
public:
RemoteFile(::FsFile &s) : m_base_file(s) { /* ... */}
virtual ~RemoteFile() { fsFileClose(std::addressof(m_base_file)); }
public:
Result Read(ams::sf::Out<s64> out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) {
return fsFileRead(std::addressof(m_base_file), offset, buffer.GetPointer(), size, option._value, reinterpret_cast<u64 *>(out.GetPointer()));
}
Result Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size, fs::WriteOption option) {
return fsFileWrite(std::addressof(m_base_file), offset, buffer.GetPointer(), size, option._value);
}
Result Flush(){
return fsFileFlush(std::addressof(m_base_file));
}
Result SetSize(s64 size) {
return fsFileSetSize(std::addressof(m_base_file), size);
}
Result GetSize(ams::sf::Out<s64> out) {
return fsFileGetSize(std::addressof(m_base_file), out.GetPointer());
}
Result OperateRange(ams::sf::Out<fs::FileQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
static_assert(sizeof(::FsRangeInfo) == sizeof(fs::FileQueryRangeInfo));
return fsFileOperateRange(std::addressof(m_base_file), static_cast<::FsOperationId>(op_id), offset, size, reinterpret_cast<::FsRangeInfo *>(out.GetPointer()));
}
Result OperateRangeWithBuffer(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 op_id, s64 offset, s64 size) {
AMS_UNUSED(out_buf, in_buf, op_id, offset, size);
AMS_ABORT("TODO");
}
};
static_assert(fssrv::sf::IsIFile<RemoteFile>);
class RemoteDirectory {
NON_COPYABLE(RemoteDirectory);
NON_MOVEABLE(RemoteDirectory);
private:
::FsDir m_base_dir;
public:
RemoteDirectory(::FsDir &s) : m_base_dir(s) { /* ... */}
virtual ~RemoteDirectory() { fsDirClose(std::addressof(m_base_dir)); }
public:
Result Read(ams::sf::Out<s64> out, const ams::sf::OutBuffer &out_entries) {
static_assert(sizeof(::FsDirectoryEntry) == sizeof(fs::DirectoryEntry));
return fsDirRead(std::addressof(m_base_dir), out.GetPointer(), out_entries.GetSize() / sizeof(fs::DirectoryEntry), reinterpret_cast<::FsDirectoryEntry *>(out_entries.GetPointer()));
}
Result GetEntryCount(ams::sf::Out<s64> out) {
return fsDirGetEntryCount(std::addressof(m_base_dir), out.GetPointer());
}
};
static_assert(fssrv::sf::IsIDirectory<RemoteDirectory>);
class RemoteFileSystem {
NON_COPYABLE(RemoteFileSystem);
NON_MOVEABLE(RemoteFileSystem);
private:
::FsFileSystem m_base_fs;
public:
RemoteFileSystem(::FsFileSystem &s) : m_base_fs(s) { /* ... */}
virtual ~RemoteFileSystem() { fsFsClose(std::addressof(m_base_fs)); }
public:
/* Command API. */
Result CreateFile(const fssrv::sf::Path &path, s64 size, s32 option) {
return fsFsCreateFile(std::addressof(m_base_fs), path.str, size, option);
}
Result DeleteFile(const fssrv::sf::Path &path) {
return fsFsDeleteFile(std::addressof(m_base_fs), path.str);
}
Result CreateDirectory(const fssrv::sf::Path &path) {
return fsFsCreateDirectory(std::addressof(m_base_fs), path.str);
}
Result DeleteDirectory(const fssrv::sf::Path &path) {
return fsFsDeleteDirectory(std::addressof(m_base_fs), path.str);
}
Result DeleteDirectoryRecursively(const fssrv::sf::Path &path) {
return fsFsDeleteDirectoryRecursively(std::addressof(m_base_fs), path.str);
}
Result RenameFile(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
return fsFsRenameFile(std::addressof(m_base_fs), old_path.str, new_path.str);
}
Result RenameDirectory(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
return fsFsRenameDirectory(std::addressof(m_base_fs), old_path.str, new_path.str);
}
Result GetEntryType(ams::sf::Out<u32> out, const fssrv::sf::Path &path) {
static_assert(sizeof(::FsDirEntryType) == sizeof(u32));
return fsFsGetEntryType(std::addressof(m_base_fs), path.str, reinterpret_cast<::FsDirEntryType *>(out.GetPointer()));
}
Result Commit() {
return fsFsCommit(std::addressof(m_base_fs));
}
Result GetFreeSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
return fsFsGetFreeSpace(std::addressof(m_base_fs), path.str, out.GetPointer());
}
Result GetTotalSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
return fsFsGetTotalSpace(std::addressof(m_base_fs), path.str, out.GetPointer());
}
Result CleanDirectoryRecursively(const fssrv::sf::Path &path) {
return fsFsCleanDirectoryRecursively(std::addressof(m_base_fs), path.str);
}
Result GetFileTimeStampRaw(ams::sf::Out<fs::FileTimeStampRaw> out, const fssrv::sf::Path &path) {
static_assert(sizeof(fs::FileTimeStampRaw) == sizeof(::FsTimeStampRaw));
return fsFsGetFileTimeStampRaw(std::addressof(m_base_fs), path.str, reinterpret_cast<::FsTimeStampRaw *>(out.GetPointer()));
}
Result QueryEntry(const ams::sf::OutBuffer &out_buf, const ams::sf::InBuffer &in_buf, s32 query_id, const fssrv::sf::Path &path) {
return fsFsQueryEntry(std::addressof(m_base_fs), out_buf.GetPointer(), out_buf.GetSize(), in_buf.GetPointer(), in_buf.GetSize(), path.str, static_cast<FsFileSystemQueryId>(query_id));
}
Result OpenFile(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFile>> out, const fssrv::sf::Path &path, u32 mode);
Result OpenDirectory(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDirectory>> out, const fssrv::sf::Path &path, u32 mode);
};
static_assert(fssrv::sf::IsIFileSystem<RemoteFileSystem>);
#endif
}

View File

@ -30,21 +30,9 @@ namespace ams::fssrv::impl {
class StorageInterfaceAdapter {
NON_COPYABLE(StorageInterfaceAdapter);
private:
/* TODO: Nintendo uses fssystem::AsynchronousAccessStorage here. */
std::shared_ptr<fs::IStorage> m_base_storage;
util::unique_lock<fssystem::SemaphoreAdapter> m_open_count_semaphore;
os::ReaderWriterLock m_invalidation_lock;
/* TODO: DataStorageContext. */
bool m_deep_retry_enabled = false;
public:
StorageInterfaceAdapter(fs::IStorage *storage);
StorageInterfaceAdapter(std::unique_ptr<fs::IStorage> storage);
explicit StorageInterfaceAdapter(std::shared_ptr<fs::IStorage> storage);
/* TODO: Other constructors. */
~StorageInterfaceAdapter();
private:
util::optional<std::shared_lock<os::ReaderWriterLock>> AcquireCacheInvalidationReadLock();
explicit StorageInterfaceAdapter(std::shared_ptr<fs::IStorage> &&storage) : m_base_storage(std::move(storage)) { /* ... */ }
public:
/* Command API. */
Result Read(s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size);
@ -56,4 +44,43 @@ namespace ams::fssrv::impl {
};
static_assert(fssrv::sf::IsIStorage<StorageInterfaceAdapter>);
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteStorage {
NON_COPYABLE(RemoteStorage);
NON_MOVEABLE(RemoteStorage);
private:
::FsStorage m_base_storage;
public:
RemoteStorage(::FsStorage &s) : m_base_storage(s) { /* ... */}
virtual ~RemoteStorage() { fsStorageClose(std::addressof(m_base_storage)); }
public:
Result Read(s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size) {
return fsStorageRead(std::addressof(m_base_storage), offset, buffer.GetPointer(), size);
}
Result Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size) {
return fsStorageWrite(std::addressof(m_base_storage), offset, buffer.GetPointer(), size);
}
Result Flush(){
return fsStorageFlush(std::addressof(m_base_storage));
}
Result SetSize(s64 size) {
return fsStorageSetSize(std::addressof(m_base_storage), size);
}
Result GetSize(ams::sf::Out<s64> out) {
return fsStorageGetSize(std::addressof(m_base_storage), out.GetPointer());
}
Result OperateRange(ams::sf::Out<fs::StorageQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
static_assert(sizeof(::FsRangeInfo) == sizeof(fs::StorageQueryRangeInfo));
return fsStorageOperateRange(std::addressof(m_base_storage), static_cast<::FsOperationId>(op_id), offset, size, reinterpret_cast<::FsRangeInfo *>(out.GetPointer()));
}
};
static_assert(fssrv::sf::IsIStorage<RemoteStorage>);
#endif
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/sf.hpp>
/* TODO */
#define AMS_FSSRV_I_DEVICE_OPERATOR_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, IsSdCardInserted, (ams::sf::Out<bool> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 200, Result, IsGameCardInserted, (ams::sf::Out<bool> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 202, Result, GetGameCardHandle, (ams::sf::Out<u32> out), (out))
AMS_SF_DEFINE_INTERFACE(ams::fssrv::sf, IDeviceOperator, AMS_FSSRV_I_DEVICE_OPERATOR_INTERFACE_INFO)

View File

@ -17,130 +17,133 @@
#include <vapours.hpp>
#include <stratosphere/sf.hpp>
#include <stratosphere/fssrv/sf/fssrv_sf_ifilesystem.hpp>
#include <stratosphere/fssrv/sf/fssrv_sf_istorage.hpp>
#include <stratosphere/fssrv/sf/fssrv_sf_i_device_operator.hpp>
#include <stratosphere/fssrv/sf/fssrv_sf_i_event_notifier.hpp>
#define AMS_FSSRV_I_FILE_SYSTEM_PROXY_INTERFACE_INFO(C, H) \
/* AMS_SF_METHOD_INFO(C, H, 0, Result, OpenFileSystem, (TODO), (TODO), hos::Version_Min, hos::Version_1_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1, Result, SetCurrentProcess, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 2, Result, OpenDataFileSystemByCurrentProcess, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 7, Result, OpenFileSystemWithPatch, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 8, Result, OpenFileSystemWithId, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 9, Result, OpenDataFileSystemByProgramId, (TODO), (TODO), hos::Version_3_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 11, Result, OpenBisFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 12, Result, OpenBisStorage, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 13, Result, InvalidateBisCache, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 17, Result, OpenHostFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 18, Result, OpenSdCardFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 19, Result, FormatSdCardFileSystem, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 21, Result, DeleteSaveDataFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 22, Result, CreateSaveDataFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 23, Result, CreateSaveDataFileSystemBySystemSaveDataId, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 24, Result, RegisterSaveDataFileSystemAtomicDeletion, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 25, Result, DeleteSaveDataFileSystemBySaveDataSpaceId, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 26, Result, FormatSdCardDryRun, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 27, Result, IsExFatSupported, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 28, Result, DeleteSaveDataFileSystemBySaveDataAttribute, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 30, Result, OpenGameCardStorage, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 31, Result, OpenGameCardFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 32, Result, ExtendSaveDataFileSystem, (TODO), (TODO), hos::Version_3_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 33, Result, DeleteCacheStorage, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 34, Result, GetCacheStorageSize, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 35, Result, CreateSaveDataFileSystemWithHashSalt, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 36, Result, OpenHostFileSystemWithOption, (TODO), (TODO), hos::Version_9_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 51, Result, OpenSaveDataFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 52, Result, OpenSaveDataFileSystemBySystemSaveDataId, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 53, Result, OpenReadOnlySaveDataFileSystem, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 57, Result, ReadSaveDataFileSystemExtraDataBySaveDataSpaceId, (TODO), (TODO), hos::Version_3_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 58, Result, ReadSaveDataFileSystemExtraData, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 59, Result, WriteSaveDataFileSystemExtraData, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 60, Result, OpenSaveDataInfoReader, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 61, Result, OpenSaveDataInfoReaderBySaveDataSpaceId, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 62, Result, OpenSaveDataInfoReaderOnlyCacheStorage, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 64, Result, OpenSaveDataInternalStorageFileSystem, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 65, Result, UpdateSaveDataMacForDebug, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 66, Result, WriteSaveDataFileSystemExtraDataWithMask, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 67, Result, FindSaveDataWithFilter, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 68, Result, OpenSaveDataInfoReaderWithFilter, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 69, Result, ReadSaveDataFileSystemExtraDataBySaveDataAttribute, (TODO), (TODO), hos::Version_8_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 70, Result, WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, (TODO), (TODO), hos::Version_8_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 71, Result, ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, (TODO), (TODO), hos::Version_10_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 80, Result, OpenSaveDataMetaFile, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 81, Result, OpenSaveDataTransferManager, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 82, Result, OpenSaveDataTransferManagerVersion2, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 83, Result, OpenSaveDataTransferProhibiter, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 84, Result, ListAccessibleSaveDataOwnerId, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 85, Result, OpenSaveDataTransferManagerForSaveDataRepair, (TODO), (TODO), hos::Version_9_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 86, Result, OpenSaveDataMover, (TODO), (TODO), hos::Version_10_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 87, Result, OpenSaveDataTransferManagerForRepair, (TODO), (TODO), hos::Version_11_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 100, Result, OpenImageDirectoryFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 101, Result, OpenBaseFileSystem, (TODO), (TODO), hos::Version_11_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 102, Result, FormatBaseFileSystem, (TODO), (TODO), hos::Version_12_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 110, Result, OpenContentStorageFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 120, Result, OpenCloudBackupWorkStorageFileSystem, (TODO), (TODO), hos::Version_6_0_0, hos::Version_9_2_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 130, Result, OpenCustomStorageFileSystem, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 200, Result, OpenDataStorageByCurrentProcess, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 201, Result, OpenDataStorageByProgramId, (TODO), (TODO), hos::Version_3_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 202, Result, OpenDataStorageByDataId, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 203, Result, OpenPatchDataStorageByCurrentProcess, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 204, Result, OpenDataFileSystemWithProgramIndex, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 205, Result, OpenDataStorageWithProgramIndex, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 206, Result, OpenDataStorageByPath, (TODO), (TODO), hos::Version_13_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 400, Result, OpenDeviceOperator, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 500, Result, OpenSdCardDetectionEventNotifier, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 501, Result, OpenGameCardDetectionEventNotifier, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 510, Result, OpenSystemDataUpdateEventNotifier, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 511, Result, NotifySystemDataUpdateEvent, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 520, Result, SimulateDeviceDetectionEvent, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 600, Result, SetCurrentPosixTime, (TODO), (TODO), hos::Version_Min, hos::Version_3_0_2) */ \
/* AMS_SF_METHOD_INFO(C, H, 601, Result, QuerySaveDataTotalSize, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 602, Result, VerifySaveDataFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 603, Result, CorruptSaveDataFileSystem, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 604, Result, CreatePaddingFile, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 605, Result, DeleteAllPaddingFiles, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 606, Result, GetRightsId, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 607, Result, RegisterExternalKey, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 608, Result, UnregisterAllExternalKey, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 609, Result, GetRightsIdByPath, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 610, Result, GetRightsIdAndKeyGenerationByPath, (TODO), (TODO), hos::Version_3_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 611, Result, SetCurrentPosixTimeWithTimeDifference, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 612, Result, GetFreeSpaceSizeForSaveData, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 613, Result, VerifySaveDataFileSystemBySaveDataSpaceId, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 614, Result, CorruptSaveDataFileSystemBySaveDataSpaceId, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 615, Result, QuerySaveDataInternalStorageTotalSize, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 616, Result, GetSaveDataCommitId, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 617, Result, UnregisterExternalKey, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 620, Result, SetSdCardEncryptionSeed, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 630, Result, SetSdCardAccessibility, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 631, Result, IsSdCardAccessible, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 640, Result, IsSignedSystemPartitionOnSdCardValid, (TODO), (TODO), hos::Version_4_0_0, hos::Version_7_0_1) */ \
/* AMS_SF_METHOD_INFO(C, H, 700, Result, OpenAccessFailureDetectionEventNotifier, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 701, Result, GetAccessFailureDetectionEvent, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 702, Result, IsAccessFailureDetected, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 710, Result, ResolveAccessFailure, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 720, Result, AbandonAccessFailure, (TODO), (TODO), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 800, Result, GetAndClearErrorInfo, (TODO), (TODO), hos::Version_2_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 810, Result, RegisterProgramIndexMapInfo, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1000, Result, SetBisRootForHost, (TODO), (TODO), hos::Version_Min, hos::Version_9_2_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1001, Result, SetSaveDataSize, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1002, Result, SetSaveDataRootPath, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1003, Result, DisableAutoSaveDataCreation, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1004, Result, SetGlobalAccessLogMode, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1005, Result, GetGlobalAccessLogMode, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1006, Result, OutputAccessLogToSdCard, (TODO), (TODO)) */ \
/* AMS_SF_METHOD_INFO(C, H, 1007, Result, RegisterUpdatePartition, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1008, Result, OpenRegisteredUpdatePartition, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1009, Result, GetAndClearMemoryReportInfo, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1010, Result, SetDataStorageRedirectTarget, (TODO), (TODO), hos::Version_5_1_0, hos::Version_6_2_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1011, Result, GetProgramIndexForAccessLog, (TODO), (TODO), hos::Version_7_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1012, Result, GetFsStackUsage, (TODO), (TODO), hos::Version_9_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1013, Result, UnsetSaveDataRootPath, (TODO), (TODO), hos::Version_9_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1014, Result, OutputMultiProgramTagAccessLog, (TODO), (TODO), hos::Version_10_0_0, hos::Version_10_2_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1016, Result, FlushAccessLogOnSdCard, (TODO), (TODO), hos::Version_11_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1017, Result, OutputApplicationInfoAccessLog, (TODO), (TODO), hos::Version_11_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1018, Result, SetDebugOption, (TODO), (TODO), hos::Version_13_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1019, Result, UnsetDebugOption, (TODO), (TODO), hos::Version_13_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1100, Result, OverrideSaveDataTransferTokenSignVerificationKey, (TODO), (TODO), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1110, Result, CorruptSaveDataFileSystemByOffset, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1200, Result, OpenMultiCommitManager, (TODO), (TODO), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1300, Result, OpenBisWiper, (TODO), (TODO), hos::Version_10_0_0) */
#define AMS_FSSRV_I_FILE_SYSTEM_PROXY_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 type), (out, path, type), hos::Version_Min, hos::Version_1_0_0) \
AMS_SF_METHOD_INFO(C, H, 1, Result, SetCurrentProcess, (const ams::sf::ClientProcessId &client_pid), (client_pid)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, OpenDataFileSystemByCurrentProcess, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenFileSystemWithPatch, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 type), (out, program_id, type), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, OpenFileSystemWithId, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u64 program_id, u32 type), (out, path, program_id, type), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, Result, OpenDataFileSystemByProgramId, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id), (out, program_id), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 11, Result, OpenBisFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 id), (out, path, id)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, OpenBisStorage, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 id), (out, id)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, InvalidateBisCache, (), ()) \
AMS_SF_METHOD_INFO(C, H, 17, Result, OpenHostFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path), (out, path)) \
AMS_SF_METHOD_INFO(C, H, 18, Result, OpenSdCardFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 19, Result, FormatSdCardFileSystem, (), (), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 21, Result, DeleteSaveDataFileSystem, (u64 save_data_id), (save_data_id)) \
AMS_SF_METHOD_INFO(C, H, 22, Result, CreateSaveDataFileSystem, (const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info), (attribute, creation_info, meta_info)) \
AMS_SF_METHOD_INFO(C, H, 23, Result, CreateSaveDataFileSystemBySystemSaveDataId, (const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info), (attribute, creation_info)) \
AMS_SF_METHOD_INFO(C, H, 24, Result, RegisterSaveDataFileSystemAtomicDeletion, (const ams::sf::InBuffer &save_data_ids), (save_data_ids)) \
AMS_SF_METHOD_INFO(C, H, 25, Result, DeleteSaveDataFileSystemBySaveDataSpaceId, (u8 indexer_space_id, u64 save_data_id), (indexer_space_id, save_data_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 26, Result, FormatSdCardDryRun, (), (), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 27, Result, IsExFatSupported, (ams::sf::Out<bool> out), (out), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 28, Result, DeleteSaveDataFileSystemBySaveDataAttribute, (u8 space_id, const fs::SaveDataAttribute &attribute), (space_id, attribute), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 30, Result, OpenGameCardStorage, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 handle, u32 partition), (out, handle, partition)) \
AMS_SF_METHOD_INFO(C, H, 31, Result, OpenGameCardFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 handle, u32 partition), (out, handle, partition)) \
AMS_SF_METHOD_INFO(C, H, 32, Result, ExtendSaveDataFileSystem, (u8 space_id, u64 save_data_id, s64 available_size, s64 journal_size), (space_id, save_data_id, available_size, journal_size), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 33, Result, DeleteCacheStorage, (u16 index), (index), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 34, Result, GetCacheStorageSize, (ams::sf::Out<s64> out_size, ams::sf::Out<s64> out_journal_size, u16 index), (out_size, out_journal_size, index), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 35, Result, CreateSaveDataFileSystemWithHashSalt, (const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info, const fs::HashSalt &salt), (attribute, creation_info, meta_info, salt), hos::Version_6_0_0) \
AMS_SF_METHOD_INFO(C, H, 36, Result, OpenHostFileSystemWithOption, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 option), (out, path, option), hos::Version_9_0_0) \
AMS_SF_METHOD_INFO(C, H, 51, Result, OpenSaveDataFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute), (out, space_id, attribute)) \
AMS_SF_METHOD_INFO(C, H, 52, Result, OpenSaveDataFileSystemBySystemSaveDataId, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute), (out, space_id, attribute)) \
AMS_SF_METHOD_INFO(C, H, 53, Result, OpenReadOnlySaveDataFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute), (out, space_id, attribute), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 57, Result, ReadSaveDataFileSystemExtraDataBySaveDataSpaceId, (const ams::sf::OutBuffer &buffer, u8 space_id, u64 save_data_id), (buffer, space_id, save_data_id), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 58, Result, ReadSaveDataFileSystemExtraData, (const ams::sf::OutBuffer &buffer, u64 save_data_id), (buffer, save_data_id)) \
AMS_SF_METHOD_INFO(C, H, 59, Result, WriteSaveDataFileSystemExtraData, (u64 save_data_id, u8 space_id, const ams::sf::InBuffer &buffer), (save_data_id, space_id, buffer), hos::Version_2_0_0) \
/* AMS_SF_METHOD_INFO(C, H, 60, Result, OpenSaveDataInfoReader, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 61, Result, OpenSaveDataInfoReaderBySaveDataSpaceId, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 62, Result, OpenSaveDataInfoReaderOnlyCacheStorage, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 64, Result, OpenSaveDataInternalStorageFileSystem, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 65, Result, UpdateSaveDataMacForDebug, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 66, Result, WriteSaveDataFileSystemExtraDataWithMask, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 67, Result, FindSaveDataWithFilter, (), (), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 68, Result, OpenSaveDataInfoReaderWithFilter, (), (), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 69, Result, ReadSaveDataFileSystemExtraDataBySaveDataAttribute, (), (), hos::Version_8_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 70, Result, WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, (), (), hos::Version_8_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 71, Result, ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, (), (), hos::Version_10_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 80, Result, OpenSaveDataMetaFile, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 81, Result, OpenSaveDataTransferManager, (), (), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 82, Result, OpenSaveDataTransferManagerVersion2, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 83, Result, OpenSaveDataTransferProhibiter, (), (), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 84, Result, ListAccessibleSaveDataOwnerId, (), (), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 85, Result, OpenSaveDataTransferManagerForSaveDataRepair, (), (), hos::Version_9_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 86, Result, OpenSaveDataMover, (), (), hos::Version_10_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 87, Result, OpenSaveDataTransferManagerForRepair, (), (), hos::Version_11_0_0) */ \
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenImageDirectoryFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id), (out, id)) \
/* AMS_SF_METHOD_INFO(C, H, 101, Result, OpenBaseFileSystem, (), (), hos::Version_11_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 102, Result, FormatBaseFileSystem, (), (), hos::Version_12_0_0) */ \
AMS_SF_METHOD_INFO(C, H, 110, Result, OpenContentStorageFileSystem, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id), (out, id)) \
/* AMS_SF_METHOD_INFO(C, H, 120, Result, OpenCloudBackupWorkStorageFileSystem, (), (), hos::Version_6_0_0, hos::Version_9_2_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 130, Result, OpenCustomStorageFileSystem, (), (), hos::Version_7_0_0) */ \
AMS_SF_METHOD_INFO(C, H, 200, Result, OpenDataStorageByCurrentProcess, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 201, Result, OpenDataStorageByProgramId, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::ProgramId program_id), (out, program_id), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 202, Result, OpenDataStorageByDataId, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::DataId data_id, u8 storage_id), (out, data_id, storage_id)) \
AMS_SF_METHOD_INFO(C, H, 203, Result, OpenPatchDataStorageByCurrentProcess, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 204, Result, OpenDataFileSystemWithProgramIndex, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 index), (out, index), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 205, Result, OpenDataStorageWithProgramIndex, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u8 index), (out, index), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 206, Result, OpenDataStorageByPath, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, const fssrv::sf::FspPath &path, u32 type), (out, path, type), hos::Version_13_0_0) \
AMS_SF_METHOD_INFO(C, H, 400, Result, OpenDeviceOperator, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDeviceOperator>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 500, Result, OpenSdCardDetectionEventNotifier, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 501, Result, OpenGameCardDetectionEventNotifier, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 510, Result, OpenSystemDataUpdateEventNotifier, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out), (out), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 511, Result, NotifySystemDataUpdateEvent, (), (), hos::Version_5_0_0) \
/* AMS_SF_METHOD_INFO(C, H, 520, Result, SimulateDeviceDetectionEvent, (), (), hos::Version_6_0_0) */ \
AMS_SF_METHOD_INFO(C, H, 600, Result, SetCurrentPosixTime, (s64 posix_time), (posix_time), hos::Version_Min, hos::Version_3_0_2) \
/* AMS_SF_METHOD_INFO(C, H, 601, Result, QuerySaveDataTotalSize, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 602, Result, VerifySaveDataFileSystem, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 603, Result, CorruptSaveDataFileSystem, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 604, Result, CreatePaddingFile, (), ()) */ \
/* AMS_SF_METHOD_INFO(C, H, 605, Result, DeleteAllPaddingFiles, (), ()) */ \
AMS_SF_METHOD_INFO(C, H, 606, Result, GetRightsId, (ams::sf::Out<fs::RightsId> out, ncm::ProgramId program_id, ncm::StorageId storage_id), (out, program_id, storage_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 607, Result, RegisterExternalKey, (const fs::RightsId &rights_id, const spl::AccessKey &access_key), (rights_id, access_key), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 608, Result, UnregisterAllExternalKey, (), (), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 609, Result, GetRightsIdByPath, (ams::sf::Out<fs::RightsId> out, const fssrv::sf::FspPath &path), (out, path), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 610, Result, GetRightsIdAndKeyGenerationByPath, (ams::sf::Out<fs::RightsId> out, ams::sf::Out<u8> out_key_generation, const fssrv::sf::FspPath &path), (out, out_key_generation, path), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 611, Result, SetCurrentPosixTimeWithTimeDifference, (s64 posix_time, s32 time_difference), (posix_time, time_difference), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 612, Result, GetFreeSpaceSizeForSaveData, (ams::sf::Out<s64> out, u8 space_id), (out, space_id), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 613, Result, VerifySaveDataFileSystemBySaveDataSpaceId, (), (), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 614, Result, CorruptSaveDataFileSystemBySaveDataSpaceId, (), (), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 615, Result, QuerySaveDataInternalStorageTotalSize, (), (), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 616, Result, GetSaveDataCommitId, (), (), hos::Version_6_0_0) \
AMS_SF_METHOD_INFO(C, H, 617, Result, UnregisterExternalKey, (const fs::RightsId &rights_id), (rights_id), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 620, Result, SetSdCardEncryptionSeed, (const fs::EncryptionSeed &seed), (seed), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 630, Result, SetSdCardAccessibility, (bool accessible), (accessible), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 631, Result, IsSdCardAccessible, (ams::sf::Out<bool> out), (out), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 640, Result, IsSignedSystemPartitionOnSdCardValid, (ams::sf::Out<bool> out), (out), hos::Version_4_0_0, hos::Version_7_0_1) \
AMS_SF_METHOD_INFO(C, H, 700, Result, OpenAccessFailureDetectionEventNotifier, (), (), hos::Version_5_0_0) \
/* AMS_SF_METHOD_INFO(C, H, 701, Result, GetAccessFailureDetectionEvent, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 702, Result, IsAccessFailureDetected, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 710, Result, ResolveAccessFailure, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 720, Result, AbandonAccessFailure, (), (), hos::Version_5_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 800, Result, GetAndClearErrorInfo, (), (), hos::Version_2_0_0) */ \
AMS_SF_METHOD_INFO(C, H, 810, Result, RegisterProgramIndexMapInfo, (const ams::sf::InBuffer &buffer, s32 count), (buffer, count), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 1000, Result, SetBisRootForHost, (u32 id, const fssrv::sf::FspPath &path), (id, path), hos::Version_Min, hos::Version_9_2_0) \
AMS_SF_METHOD_INFO(C, H, 1001, Result, SetSaveDataSize, (s64 size, s64 journal_size), (size, journal_size)) \
AMS_SF_METHOD_INFO(C, H, 1002, Result, SetSaveDataRootPath, (const fssrv::sf::FspPath &path), (path)) \
AMS_SF_METHOD_INFO(C, H, 1003, Result, DisableAutoSaveDataCreation, (), ()) \
AMS_SF_METHOD_INFO(C, H, 1004, Result, SetGlobalAccessLogMode, (u32 mode), (mode)) \
AMS_SF_METHOD_INFO(C, H, 1005, Result, GetGlobalAccessLogMode, (ams::sf::Out<u32> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 1006, Result, OutputAccessLogToSdCard, (const ams::sf::InBuffer &buf), (buf)) \
AMS_SF_METHOD_INFO(C, H, 1007, Result, RegisterUpdatePartition, (), (), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 1008, Result, OpenRegisteredUpdatePartition, (ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out), (out), hos::Version_4_0_0) \
/* AMS_SF_METHOD_INFO(C, H, 1009, Result, GetAndClearMemoryReportInfo, (ams::sf::Out<fs::MemoryReportInfo> out), (out), hos::Version_4_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1010, Result, SetDataStorageRedirectTarget, (), (), hos::Version_5_1_0, hos::Version_6_2_0) */ \
AMS_SF_METHOD_INFO(C, H, 1011, Result, GetProgramIndexForAccessLog, (ams::sf::Out<u32> out_idx, ams::sf::Out<u32> out_count), (out_idx, out_count), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 1012, Result, GetFsStackUsage, (ams::sf::Out<u32> out, u32 type), (out, type), hos::Version_9_0_0) \
AMS_SF_METHOD_INFO(C, H, 1013, Result, UnsetSaveDataRootPath, (), (), hos::Version_9_0_0) \
AMS_SF_METHOD_INFO(C, H, 1014, Result, OutputMultiProgramTagAccessLog, (), (), hos::Version_10_0_0, hos::Version_10_2_0) \
AMS_SF_METHOD_INFO(C, H, 1016, Result, FlushAccessLogOnSdCard, (), (), hos::Version_11_0_0) \
AMS_SF_METHOD_INFO(C, H, 1017, Result, OutputApplicationInfoAccessLog, (), (), hos::Version_11_0_0) \
AMS_SF_METHOD_INFO(C, H, 1018, Result, RegisterDebugConfiguration, (u32 key, s64 value), (key, value), hos::Version_13_0_0) \
AMS_SF_METHOD_INFO(C, H, 1019, Result, UnregisterDebugConfiguration, (u32 key), (key), hos::Version_13_0_0) \
AMS_SF_METHOD_INFO(C, H, 1100, Result, OverrideSaveDataTransferTokenSignVerificationKey, (const ams::sf::InBuffer &buf), (buf), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 1110, Result, CorruptSaveDataFileSystemByOffset, (u8 space_id, u64 save_data_id, s64 offset), (space_id, save_data_id, offset), hos::Version_6_0_0) \
/* AMS_SF_METHOD_INFO(C, H, 1200, Result, OpenMultiCommitManager, (), (), hos::Version_6_0_0) */ \
/* AMS_SF_METHOD_INFO(C, H, 1300, Result, OpenBisWiper, (), (), hos::Version_10_0_0) */
AMS_SF_DEFINE_INTERFACE(ams::fssrv::sf, IFileSystemProxy, AMS_FSSRV_I_FILE_SYSTEM_PROXY_INTERFACE_INFO)

View File

@ -42,8 +42,11 @@ namespace ams::fssrv::sf {
return len;
}
};
static_assert(util::is_pod<Path>::value);
static_assert(util::is_pod<Path>::value && sizeof(Path) == FS_MAX_PATH);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(Path) == FS_MAX_PATH);
#endif
using FspPath = Path;

View File

@ -49,4 +49,5 @@
#include <stratosphere/fssystem/save/fssystem_hierarchical_integrity_verification_storage.hpp>
#include <stratosphere/fssystem/fssystem_integrity_romfs_storage.hpp>
#include <stratosphere/fssystem/fssystem_sha256_hash_generator.hpp>
#include <stratosphere/fssystem/fssystem_file_system_proxy_api.hpp>
#include <stratosphere/fssystem/fssystem_local_file_system.hpp>
#include <stratosphere/fssystem/fssystem_file_system_proxy_api.hpp>

View File

@ -80,8 +80,8 @@ namespace ams::fssystem {
return this->GetRetriedCountImpl();
}
void ClearPeak() const {
return this->ClearPeak();
void ClearPeak() {
return this->ClearPeakImpl();
}
protected:
virtual const std::pair<uintptr_t, size_t> AllocateBufferImpl(size_t size, const BufferAttribute &attr) = 0;

View File

@ -14,34 +14,166 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fssystem/impl/fssystem_path_resolution_filesystem.hpp>
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fssystem {
class DirectoryRedirectionFileSystem : public impl::IPathResolutionFileSystem<DirectoryRedirectionFileSystem> {
class DirectoryRedirectionFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
NON_COPYABLE(DirectoryRedirectionFileSystem);
private:
using PathResolutionFileSystem = impl::IPathResolutionFileSystem<DirectoryRedirectionFileSystem>;
friend class impl::IPathResolutionFileSystem<DirectoryRedirectionFileSystem>;
private:
char *m_before_dir;
size_t m_before_dir_len;
char *m_after_dir;
size_t m_after_dir_len;
std::unique_ptr<fs::fsa::IFileSystem> m_base_fs;
fs::Path m_before_dir;
fs::Path m_after_dir;
public:
DirectoryRedirectionFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc = false);
DirectoryRedirectionFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc = false);
DirectoryRedirectionFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs) : m_base_fs(std::move(fs)), m_before_dir(), m_after_dir() {
/* ... */
}
virtual ~DirectoryRedirectionFileSystem();
protected:
inline util::optional<std::scoped_lock<os::SdkMutex>> GetAccessorLock() const {
/* No accessor lock is needed. */
return util::nullopt;
Result InitializeWithFixedPath(const char *before, const char *after) {
R_TRY(fs::SetUpFixedPath(std::addressof(m_before_dir), before));
R_TRY(fs::SetUpFixedPath(std::addressof(m_after_dir), after));
R_SUCCEED();
}
private:
Result GetNormalizedDirectoryPath(char **out, size_t *out_size, const char *dir);
Result Initialize(const char *before, const char *after);
Result ResolveFullPath(char *out, size_t out_size, const char *relative_path);
Result ResolveFullPath(fs::Path *out, const fs::Path &path) {
if (path.IsMatchHead(m_before_dir.GetString(), m_before_dir.GetLength())) {
R_TRY(out->InitializeWithFormat("%s%s", m_after_dir.GetString(), path.GetString() + m_before_dir.GetLength()));
R_TRY(out->Normalize(fs::PathFlags{}));
} else {
R_TRY(out->Initialize(path));
}
R_SUCCEED();
}
public:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int option) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CreateFile(full_path, size, option));
}
virtual Result DoDeleteFile(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteFile(full_path));
}
virtual Result DoCreateDirectory(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CreateDirectory(full_path));
}
virtual Result DoDeleteDirectory(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteDirectory(full_path));
}
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteDirectoryRecursively(full_path));
}
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override {
fs::Path old_full_path;
fs::Path new_full_path;
R_TRY(this->ResolveFullPath(std::addressof(old_full_path), old_path));
R_TRY(this->ResolveFullPath(std::addressof(new_full_path), new_path));
R_RETURN(m_base_fs->RenameFile(old_full_path, new_full_path));
}
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override {
fs::Path old_full_path;
fs::Path new_full_path;
R_TRY(this->ResolveFullPath(std::addressof(old_full_path), old_path));
R_TRY(this->ResolveFullPath(std::addressof(new_full_path), new_path));
R_RETURN(m_base_fs->RenameDirectory(old_full_path, new_full_path));
}
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetEntryType(out, full_path));
}
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->OpenFile(out_file, full_path, mode));
}
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->OpenDirectory(out_dir, full_path, mode));
}
virtual Result DoCommit() override {
R_RETURN(m_base_fs->Commit());
}
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetFreeSpaceSize(out, full_path));
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetTotalSpaceSize(out, full_path));
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CleanDirectoryRecursively(full_path));
}
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetFileTimeStampRaw(out, full_path));
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->QueryEntry(dst, dst_size, src, src_size, query, full_path));
}
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override {
R_RETURN(m_base_fs->CommitProvisionally(counter));
}
virtual Result DoRollback() override {
R_RETURN(m_base_fs->Rollback());
}
virtual Result DoFlush() override {
R_RETURN(m_base_fs->Flush());
}
};
}

View File

@ -14,51 +14,56 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fssystem/impl/fssystem_path_resolution_filesystem.hpp>
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fssystem {
class DirectorySaveDataFileSystem : public impl::IPathResolutionFileSystem<DirectorySaveDataFileSystem> {
class DirectorySaveDataFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
NON_COPYABLE(DirectorySaveDataFileSystem);
private:
using PathResolutionFileSystem = impl::IPathResolutionFileSystem<DirectorySaveDataFileSystem>;
friend class impl::IPathResolutionFileSystem<DirectorySaveDataFileSystem>;
private:
os::SdkMutex m_accessor_mutex;
s32 m_open_writable_files;
public:
DirectorySaveDataFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs);
DirectorySaveDataFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs);
Result Initialize();
std::unique_ptr<fs::fsa::IFileSystem> m_unique_fs;
fs::fsa::IFileSystem * const m_base_fs;
os::SdkMutex m_accessor_mutex = {};
s32 m_open_writable_files = 0;
bool m_is_journaling_supported = false;
bool m_is_multi_commit_supported = false;
bool m_is_journaling_enabled = false;
virtual ~DirectorySaveDataFileSystem();
protected:
inline util::optional<std::scoped_lock<os::SdkMutex>> GetAccessorLock() {
/* We have a real accessor lock that we want to use. */
return util::make_optional<std::scoped_lock<os::SdkMutex>>(m_accessor_mutex);
}
/* Extension member to ensure proper savedata locking. */
std::unique_ptr<fs::fsa::IFile> m_lock_file = nullptr;
public:
DirectorySaveDataFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs) : m_unique_fs(std::move(fs)), m_base_fs(m_unique_fs.get()) { /* ... */ }
DirectorySaveDataFileSystem(fs::fsa::IFileSystem *fs) : m_unique_fs(), m_base_fs(fs) { /* ... */ }
Result Initialize(bool journaling_supported, bool multi_commit_enabled, bool journaling_enabled);
private:
Result AllocateWorkBuffer(std::unique_ptr<u8[]> *out, size_t *out_size, size_t ideal_size);
Result SynchronizeDirectory(const char *dst, const char *src);
Result ResolveFullPath(char *out, size_t out_size, const char *relative_path);
Result SynchronizeDirectory(const fs::Path &dst, const fs::Path &src);
Result ResolvePath(fs::Path *out, const fs::Path &path);
Result AcquireLockFile();
public:
void OnWritableFileClose();
Result CopySaveFromFileSystem(fs::fsa::IFileSystem *save_fs);
void DecrementWriteOpenFileCount();
public:
/* Overridden from IPathResolutionFileSystem */
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
virtual Result DoCreateFile(const fs::Path &path, s64 size, int option) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
/* Overridden from IPathResolutionFileSystem but not commands. */
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;
virtual Result DoRollback() override;
/* Explicitly overridden to be not implemented. */
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) override;
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const char *path) override;
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const char *path) override;
virtual Result DoFlush() override;
};
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/fs_memory_management.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fssystem {
/* TODO: Put this in its own header? */
enum PathCaseSensitiveMode {
PathCaseSensitiveMode_CaseInsensitive = 0,
PathCaseSensitiveMode_CaseSensitive = 1,
};
class LocalFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
NON_COPYABLE(LocalFileSystem);
NON_MOVEABLE(LocalFileSystem);
private:
#if defined(ATMOSPHERE_OS_WINDOWS)
using NativeCharacterType = wchar_t;
#else
using NativeCharacterType = char;
#endif
using NativePathBuffer = std::unique_ptr<NativeCharacterType[], ::ams::fs::impl::Deleter>;
private:
fs::Path m_root_path;
fssystem::PathCaseSensitiveMode m_case_sensitive_mode;
NativePathBuffer m_native_path_buffer;
int m_native_path_length;
bool m_use_posix_time;
public:
LocalFileSystem(bool posix_time = true) : m_root_path(), m_native_path_buffer(), m_native_path_length(0), m_use_posix_time(posix_time) {
/* ... */
}
Result Initialize(const fs::Path &root_path, fssystem::PathCaseSensitiveMode case_sensitive_mode);
Result GetCaseSensitivePath(int *out_size, char *dst, size_t dst_size, const char *path, const char *work_path);
private:
Result CheckPathCaseSensitively(const NativeCharacterType *path, const NativeCharacterType *root_path, NativeCharacterType *cs_buf, size_t cs_size, bool check_case_sensitivity);
Result ResolveFullPath(NativePathBuffer *out, const fs::Path &path, int max_len, int min_len, bool check_case_sensitivity);
public:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) override;
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) override;
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;
virtual Result DoRollback() override;
public:
Result DoGetDiskFreeSpace(s64 *out_free, s64 *out_total, s64 *out_total_free, const fs::Path &path);
Result DeleteDirectoryRecursivelyInternal(const NativeCharacterType *path, bool delete_top);
};
}

View File

@ -49,18 +49,18 @@ namespace ams::fssystem {
Result GetFileBaseOffset(s64 *out_offset, const char *path);
virtual Result DoCreateFile(const char *path, s64 size, int option) override;
virtual Result DoDeleteFile(const char *path) override;
virtual Result DoCreateDirectory(const char *path) override;
virtual Result DoDeleteDirectory(const char *path) override;
virtual Result DoDeleteDirectoryRecursively(const char *path) override;
virtual Result DoRenameFile(const char *old_path, const char *new_path) override;
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
virtual Result DoCreateFile(const fs::Path &path, s64 size, int option) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoCleanDirectoryRecursively(const char *path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;

View File

@ -31,10 +31,18 @@ namespace ams::fssystem {
template<typename T, size_t Size>
class Pimpl {
private:
alignas(0x10) u8 m_storage[Size];
#if defined(ATMOSPHERE_OS_HORIZON) || defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX)
static constexpr size_t ExtraSizeToEnsureCompatibility = 0;
#elif defined(ATMOSPHERE_OS_MACOS)
static constexpr size_t ExtraSizeToEnsureCompatibility = 0x20;
#endif
static constexpr size_t StorageSize = Size + ExtraSizeToEnsureCompatibility;
private:
alignas(0x10) u8 m_storage[StorageSize];
public:
ALWAYS_INLINE Pimpl() { impl::PimplHelper<T, Size>::Construct(m_storage); }
ALWAYS_INLINE ~Pimpl() { impl::PimplHelper<T, Size>::Destroy(m_storage); }
ALWAYS_INLINE Pimpl() { impl::PimplHelper<T, StorageSize>::Construct(m_storage); }
ALWAYS_INLINE ~Pimpl() { impl::PimplHelper<T, StorageSize>::Destroy(m_storage); }
ALWAYS_INLINE T *Get() { return reinterpret_cast<T *>(m_storage + 0); }
ALWAYS_INLINE T *operator->() { return reinterpret_cast<T *>(m_storage + 0); }

View File

@ -37,6 +37,13 @@ namespace ams::fssystem {
s64 m_entry_size;
private:
Result GetFileInfo(RomFileTable::FileInfo *out, const char *path);
Result GetFileInfo(RomFileTable::FileInfo *out, const fs::Path &path) {
R_RETURN(this->GetFileInfo(out, path.GetString()));
}
Result CheckPathFormat(const fs::Path &path) const {
R_RETURN(fs::PathFormatter::CheckPathFormat(path.GetString(), fs::PathFlags{}));
}
public:
static Result GetRequiredWorkingMemorySize(size_t *out, fs::IStorage *storage);
public:
@ -48,21 +55,21 @@ namespace ams::fssystem {
fs::IStorage *GetBaseStorage();
RomFileTable *GetRomFileTable();
Result GetFileBaseOffset(s64 *out, const char *path);
Result GetFileBaseOffset(s64 *out, const fs::Path &path);
public:
virtual Result DoCreateFile(const char *path, s64 size, int flags) override;
virtual Result DoDeleteFile(const char *path) override;
virtual Result DoCreateDirectory(const char *path) override;
virtual Result DoDeleteDirectory(const char *path) override;
virtual Result DoDeleteDirectoryRecursively(const char *path) override;
virtual Result DoRenameFile(const char *old_path, const char *new_path) override;
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override;
virtual Result DoCreateFile(const fs::Path &path, s64 size, int flags) override;
virtual Result DoDeleteFile(const fs::Path &path) override;
virtual Result DoCreateDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectory(const fs::Path &path) override;
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override;
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override;
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override;
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override;
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override;
virtual Result DoCommit() override;
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override;
virtual Result DoCleanDirectoryRecursively(const char *path) override;
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override;
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override;
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override;

View File

@ -51,7 +51,7 @@ namespace ams::fssystem {
}
virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) override {
crypto::GenerateSha256Hash(dst, dst_size, src, src_size);
crypto::GenerateSha256(dst, dst_size, src, src_size);
}
};

View File

@ -14,31 +14,162 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fssystem/impl/fssystem_path_resolution_filesystem.hpp>
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fssystem {
class SubDirectoryFileSystem : public impl::IPathResolutionFileSystem<SubDirectoryFileSystem> {
class SubDirectoryFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
NON_COPYABLE(SubDirectoryFileSystem);
private:
using PathResolutionFileSystem = impl::IPathResolutionFileSystem<SubDirectoryFileSystem>;
friend class impl::IPathResolutionFileSystem<SubDirectoryFileSystem>;
private:
char *m_base_path;
size_t m_base_path_len;
std::shared_ptr<fs::fsa::IFileSystem> m_shared_fs;
fs::fsa::IFileSystem * const m_base_fs;
fs::Path m_root_path;
public:
SubDirectoryFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc = false);
SubDirectoryFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc = false);
SubDirectoryFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs) : m_shared_fs(std::move(fs)), m_base_fs(m_shared_fs.get()), m_root_path() {
/* ... */
}
virtual ~SubDirectoryFileSystem();
protected:
inline util::optional<std::scoped_lock<os::SdkMutex>> GetAccessorLock() const {
/* No accessor lock is needed. */
return util::nullopt;
SubDirectoryFileSystem(fs::fsa::IFileSystem *fs) : m_shared_fs(), m_base_fs(fs), m_root_path() {
/* ... */
}
Result Initialize(const fs::Path &path) {
R_RETURN(m_root_path.Initialize(path));
}
private:
Result Initialize(const char *bp);
Result ResolveFullPath(char *out, size_t out_size, const char *relative_path);
Result ResolveFullPath(fs::Path *out, const fs::Path &path) {
R_RETURN(out->Combine(m_root_path, path));
}
public:
virtual Result DoCreateFile(const fs::Path &path, s64 size, int option) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CreateFile(full_path, size, option));
}
virtual Result DoDeleteFile(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteFile(full_path));
}
virtual Result DoCreateDirectory(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CreateDirectory(full_path));
}
virtual Result DoDeleteDirectory(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteDirectory(full_path));
}
virtual Result DoDeleteDirectoryRecursively(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->DeleteDirectoryRecursively(full_path));
}
virtual Result DoRenameFile(const fs::Path &old_path, const fs::Path &new_path) override {
fs::Path old_full_path;
fs::Path new_full_path;
R_TRY(this->ResolveFullPath(std::addressof(old_full_path), old_path));
R_TRY(this->ResolveFullPath(std::addressof(new_full_path), new_path));
R_RETURN(m_base_fs->RenameFile(old_full_path, new_full_path));
}
virtual Result DoRenameDirectory(const fs::Path &old_path, const fs::Path &new_path) override {
fs::Path old_full_path;
fs::Path new_full_path;
R_TRY(this->ResolveFullPath(std::addressof(old_full_path), old_path));
R_TRY(this->ResolveFullPath(std::addressof(new_full_path), new_path));
R_RETURN(m_base_fs->RenameDirectory(old_full_path, new_full_path));
}
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetEntryType(out, full_path));
}
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const fs::Path &path, fs::OpenMode mode) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->OpenFile(out_file, full_path, mode));
}
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const fs::Path &path, fs::OpenDirectoryMode mode) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->OpenDirectory(out_dir, full_path, mode));
}
virtual Result DoCommit() override {
R_RETURN(m_base_fs->Commit());
}
virtual Result DoGetFreeSpaceSize(s64 *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetFreeSpaceSize(out, full_path));
}
virtual Result DoGetTotalSpaceSize(s64 *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetTotalSpaceSize(out, full_path));
}
virtual Result DoCleanDirectoryRecursively(const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->CleanDirectoryRecursively(full_path));
}
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->GetFileTimeStampRaw(out, full_path));
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const fs::Path &path) override {
fs::Path full_path;
R_TRY(this->ResolveFullPath(std::addressof(full_path), path));
R_RETURN(m_base_fs->QueryEntry(dst, dst_size, src, src_size, query, full_path));
}
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override {
R_RETURN(m_base_fs->CommitProvisionally(counter));
}
virtual Result DoRollback() override {
R_RETURN(m_base_fs->Rollback());
}
virtual Result DoFlush() override {
R_RETURN(m_base_fs->Flush());
}
};
}

View File

@ -18,21 +18,24 @@
#include <stratosphere/fs/fs_file.hpp>
#include <stratosphere/fs/fs_directory.hpp>
#include <stratosphere/fs/fs_filesystem.hpp>
#include <stratosphere/fs/fs_path_utils.hpp>
#include <stratosphere/fs/fs_path.hpp>
namespace ams::fssystem {
namespace impl {
template<typename F>
concept IterateDirectoryHandler = requires (F f, const fs::Path &path, const fs::DirectoryEntry &entry) {
{ f(path, entry) } -> std::convertible_to<::ams::Result>;
};
/* Iteration. */
template<typename OnEnterDir, typename OnExitDir, typename OnFile>
Result IterateDirectoryRecursivelyImpl(fs::fsa::IFileSystem *fs, char *work_path, size_t work_path_size, fs::DirectoryEntry *dir_ent, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
template<IterateDirectoryHandler OnEnterDir, IterateDirectoryHandler OnExitDir, IterateDirectoryHandler OnFile>
Result IterateDirectoryRecursivelyImpl(fs::fsa::IFileSystem *fs, fs::Path &work_path, fs::DirectoryEntry *dir_ent, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
/* Open the directory. */
std::unique_ptr<fs::fsa::IDirectory> dir;
R_TRY(fs->OpenDirectory(std::addressof(dir), work_path, fs::OpenDirectoryMode_All));
const size_t parent_len = strnlen(work_path, work_path_size - 1);
/* Read and handle entries. */
while (true) {
/* Read a single entry. */
@ -44,22 +47,15 @@ namespace ams::fssystem {
break;
}
/* Validate child path size. */
const size_t child_name_len = strnlen(dir_ent->name, sizeof(dir_ent->name) - 1);
const bool is_dir = dir_ent->type == fs::DirectoryEntryType_Directory;
const size_t separator_size = is_dir ? 1 : 0;
R_UNLESS(parent_len + child_name_len + separator_size < work_path_size, fs::ResultTooLongPath());
/* Set child path. */
std::strncat(work_path, dir_ent->name, work_path_size - parent_len - 1);
/* Append child path. */
R_TRY(work_path.AppendChild(dir_ent->name));
{
if (is_dir) {
if (dir_ent->type == fs::DirectoryEntryType_Directory) {
/* Enter directory. */
R_TRY(on_enter_dir(work_path, *dir_ent));
/* Append separator, recurse. */
std::strncat(work_path, "/", work_path_size - (parent_len + child_name_len) - 1);
R_TRY(IterateDirectoryRecursivelyImpl(fs, work_path, work_path_size, dir_ent, on_enter_dir, on_exit_dir, on_file));
/* Recurse. */
R_TRY(IterateDirectoryRecursivelyImpl(fs, work_path, dir_ent, on_enter_dir, on_exit_dir, on_file));
/* Exit directory. */
R_TRY(on_exit_dir(work_path, *dir_ent));
@ -68,12 +64,10 @@ namespace ams::fssystem {
R_TRY(on_file(work_path, *dir_ent));
}
}
/* Restore parent path. */
work_path[parent_len] = fs::StringTraits::NullTerminator;
R_TRY(work_path.RemoveChild());
}
return ResultSuccess();
R_SUCCEED();
}
/* TODO: Cleanup. */
@ -81,50 +75,39 @@ namespace ams::fssystem {
}
/* Iteration API */
template<typename OnEnterDir, typename OnExitDir, typename OnFile>
Result IterateDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *root_path, char *work_path, size_t work_path_size, fs::DirectoryEntry *dir_ent_buf, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
AMS_ABORT_UNLESS(work_path_size >= fs::EntryNameLengthMax + 1);
template<impl::IterateDirectoryHandler OnEnterDir, impl::IterateDirectoryHandler OnExitDir, impl::IterateDirectoryHandler OnFile>
Result IterateDirectoryRecursively(fs::fsa::IFileSystem *fs, const fs::Path &root_path, fs::DirectoryEntry *dir_ent_buf, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
/* Create work path from the root path. */
fs::Path work_path;
R_TRY(work_path.Initialize(root_path));
/* Get size of the root path. */
size_t root_path_len = strnlen(root_path, fs::EntryNameLengthMax + 1);
R_UNLESS(root_path_len <= fs::EntryNameLengthMax, fs::ResultTooLongPath());
/* Copy root path in, add a / if necessary. */
std::memcpy(work_path, root_path, root_path_len);
if (!fs::PathNormalizer::IsSeparator(work_path[root_path_len - 1])) {
work_path[root_path_len++] = fs::StringTraits::DirectorySeparator;
}
/* Make sure the result path is still valid. */
R_UNLESS(root_path_len <= fs::EntryNameLengthMax, fs::ResultTooLongPath());
work_path[root_path_len] = fs::StringTraits::NullTerminator;
return impl::IterateDirectoryRecursivelyImpl(fs, work_path, work_path_size, dir_ent_buf, on_enter_dir, on_exit_dir, on_file);
R_RETURN(impl::IterateDirectoryRecursivelyImpl(fs, work_path, dir_ent_buf, on_enter_dir, on_exit_dir, on_file));
}
template<typename OnEnterDir, typename OnExitDir, typename OnFile>
Result IterateDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *root_path, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
template<impl::IterateDirectoryHandler OnEnterDir, impl::IterateDirectoryHandler OnExitDir, impl::IterateDirectoryHandler OnFile>
Result IterateDirectoryRecursively(fs::fsa::IFileSystem *fs, const fs::Path &root_path, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
fs::DirectoryEntry dir_entry = {};
char work_path[fs::EntryNameLengthMax + 1] = {};
return IterateDirectoryRecursively(fs, root_path, work_path, sizeof(work_path), std::addressof(dir_entry), on_enter_dir, on_exit_dir, on_file);
return IterateDirectoryRecursively(fs, root_path, std::addressof(dir_entry), on_enter_dir, on_exit_dir, on_file);
}
template<typename OnEnterDir, typename OnExitDir, typename OnFile>
template<impl::IterateDirectoryHandler OnEnterDir, impl::IterateDirectoryHandler OnExitDir, impl::IterateDirectoryHandler OnFile>
Result IterateDirectoryRecursively(fs::fsa::IFileSystem *fs, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
return IterateDirectoryRecursively(fs, fs::PathNormalizer::RootPath, on_enter_dir, on_exit_dir, on_file);
return IterateDirectoryRecursively(fs, fs::MakeConstantPath("/"), on_enter_dir, on_exit_dir, on_file);
}
/* TODO: Cleanup API */
/* Copy API. */
Result CopyFile(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const char *dst_parent_path, const char *src_path, const fs::DirectoryEntry *dir_ent, void *work_buf, size_t work_buf_size);
ALWAYS_INLINE Result CopyFile(fs::fsa::IFileSystem *fs, const char *dst_parent_path, const char *src_path, const fs::DirectoryEntry *dir_ent, void *work_buf, size_t work_buf_size) {
return CopyFile(fs, fs, dst_parent_path, src_path, dir_ent, work_buf, work_buf_size);
Result CopyFile(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const fs::Path &dst_path, const fs::Path &src_path, void *work_buf, size_t work_buf_size);
ALWAYS_INLINE Result CopyFile(fs::fsa::IFileSystem *fs, const fs::Path &dst_path, const fs::Path &src_path, void *work_buf, size_t work_buf_size) {
return CopyFile(fs, fs, dst_path, src_path, work_buf, work_buf_size);
}
Result CopyDirectoryRecursively(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const char *dst_path, const char *src_path, void *work_buf, size_t work_buf_size);
ALWAYS_INLINE Result CopyDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *dst_path, const char *src_path, void *work_buf, size_t work_buf_size) {
return CopyDirectoryRecursively(fs, fs, dst_path, src_path, work_buf, work_buf_size);
Result CopyDirectoryRecursively(fs::fsa::IFileSystem *dst_fs, fs::fsa::IFileSystem *src_fs, const fs::Path &dst_path, const fs::Path &src_path, fs::DirectoryEntry *entry, void *work_buf, size_t work_buf_size);
ALWAYS_INLINE Result CopyDirectoryRecursively(fs::fsa::IFileSystem *fs, const fs::Path &dst_path, const fs::Path &src_path, fs::DirectoryEntry *entry, void *work_buf, size_t work_buf_size) {
return CopyDirectoryRecursively(fs, fs, dst_path, src_path, entry, work_buf, work_buf_size);
}
/* Semaphore adapter class. */
@ -142,32 +125,27 @@ namespace ams::fssystem {
};
/* Other utility. */
Result HasFile(bool *out, fs::fsa::IFileSystem *fs, const char *path);
Result HasDirectory(bool *out, fs::fsa::IFileSystem *fs, const char *path);
Result HasFile(bool *out, fs::fsa::IFileSystem *fs, const fs::Path &path);
Result HasDirectory(bool *out, fs::fsa::IFileSystem *fs, const fs::Path &path);
Result EnsureDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *path);
Result EnsureParentDirectoryRecursively(fs::fsa::IFileSystem *fs, const char *path);
Result EnsureDirectory(fs::fsa::IFileSystem *fs, const fs::Path &path);
template<s64 RetryMilliSeconds = 100>
template<s64 RetryMilliSeconds = 100, s32 MaxTryCount = 10>
ALWAYS_INLINE Result RetryFinitelyForTargetLocked(auto f) {
/* Retry up to 10 times, 100ms between retries. */
constexpr s32 MaxRetryCount = 10;
/* Retry sleeping between retries. */
constexpr TimeSpan RetryWaitTime = TimeSpan::FromMilliSeconds(RetryMilliSeconds);
s32 remaining_retries = MaxRetryCount;
while (true) {
R_TRY_CATCH(f()) {
R_CATCH(fs::ResultTargetLocked) {
R_UNLESS(remaining_retries > 0, fs::ResultTargetLocked());
remaining_retries--;
os::SleepThread(RetryWaitTime);
continue;
}
} R_END_TRY_CATCH;
return ResultSuccess();
Result result = f();
for (int i = 0; i < MaxTryCount && fs::ResultTargetLocked::Includes(result); ++i) {
os::SleepThread(RetryWaitTime);
result = f();
}
R_RETURN(result);
}
ALWAYS_INLINE Result RetryToAvoidTargetLocked(auto f) {
return RetryFinitelyForTargetLocked<2, 25>(f);
}
void AddCounter(void *counter, size_t counter_size, u64 value);

View File

@ -1,195 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere/fs/fs_common.hpp>
#include <stratosphere/fs/fsa/fs_ifile.hpp>
#include <stratosphere/fs/fsa/fs_idirectory.hpp>
#include <stratosphere/fs/fsa/fs_ifilesystem.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fssystem::impl {
template<typename Impl>
class IPathResolutionFileSystem : public fs::fsa::IFileSystem, public fs::impl::Newable {
NON_COPYABLE(IPathResolutionFileSystem);
private:
std::shared_ptr<fs::fsa::IFileSystem> m_shared_fs;
std::unique_ptr<fs::fsa::IFileSystem> m_unique_fs;
bool m_unc_preserved;
protected:
fs::fsa::IFileSystem * const m_base_fs;
public:
IPathResolutionFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, bool unc = false) : m_shared_fs(std::move(fs)), m_unc_preserved(unc), m_base_fs(m_shared_fs.get()) {
/* ... */
}
IPathResolutionFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, bool unc = false) : m_unique_fs(std::move(fs)), m_unc_preserved(unc), m_base_fs(m_unique_fs.get()) {
/* ... */
}
virtual ~IPathResolutionFileSystem() { /* ... */ }
protected:
constexpr inline bool IsUncPreserved() const {
return m_unc_preserved;
}
public:
virtual Result DoCreateFile(const char *path, s64 size, int option) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->CreateFile(full_path, size, option);
}
virtual Result DoDeleteFile(const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->DeleteFile(full_path);
}
virtual Result DoCreateDirectory(const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->CreateDirectory(full_path);
}
virtual Result DoDeleteDirectory(const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->DeleteDirectory(full_path);
}
virtual Result DoDeleteDirectoryRecursively(const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->DeleteDirectoryRecursively(full_path);
}
virtual Result DoRenameFile(const char *old_path, const char *new_path) override {
char old_full_path[fs::EntryNameLengthMax + 1];
char new_full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(old_full_path, sizeof(old_full_path), old_path));
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(new_full_path, sizeof(new_full_path), new_path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->RenameFile(old_full_path, new_full_path);
}
virtual Result DoRenameDirectory(const char *old_path, const char *new_path) override {
char old_full_path[fs::EntryNameLengthMax + 1];
char new_full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(old_full_path, sizeof(old_full_path), old_path));
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(new_full_path, sizeof(new_full_path), new_path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->RenameDirectory(old_full_path, new_full_path);
}
virtual Result DoGetEntryType(fs::DirectoryEntryType *out, const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->GetEntryType(out, full_path);
}
virtual Result DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->OpenFile(out_file, full_path, mode);
}
virtual Result DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->OpenDirectory(out_dir, full_path, mode);
}
virtual Result DoCommit() override {
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->Commit();
}
virtual Result DoGetFreeSpaceSize(s64 *out, const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->GetFreeSpaceSize(out, full_path);
}
virtual Result DoGetTotalSpaceSize(s64 *out, const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->GetTotalSpaceSize(out, full_path);
}
virtual Result DoCleanDirectoryRecursively(const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->CleanDirectoryRecursively(full_path);
}
virtual Result DoGetFileTimeStampRaw(fs::FileTimeStampRaw *out, const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->GetFileTimeStampRaw(out, full_path);
}
virtual Result DoQueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fs::fsa::QueryId query, const char *path) override {
char full_path[fs::EntryNameLengthMax + 1];
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->QueryEntry(dst, dst_size, src, src_size, query, full_path);
}
/* These aren't accessible as commands. */
virtual Result DoCommitProvisionally(s64 counter) override {
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->CommitProvisionally(counter);
}
virtual Result DoRollback() override {
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->Rollback();
}
virtual Result DoFlush() override {
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
return m_base_fs->Flush();
}
};
}

View File

@ -105,7 +105,7 @@ namespace ams::fssystem::save {
NON_COPYABLE(HierarchicalIntegrityVerificationStorage);
NON_MOVEABLE(HierarchicalIntegrityVerificationStorage);
private:
friend class HierarchicalIntegrityVerificationMetaInformation;
friend struct HierarchicalIntegrityVerificationMetaInformation;
protected:
static constexpr s64 HashSize = crypto::Sha256Generator::HashSize;
static constexpr size_t MaxLayers = IntegrityMaxLayerCount;

View File

@ -59,7 +59,7 @@ namespace ams::gpio::driver {
virtual Result SetDebounceTime(Pad *pad, s32 ms) = 0;
virtual Result GetUnknown22(u32 *out) = 0;
virtual void Unknown23();
virtual void Unknown23() = 0;
virtual Result SetValueForSleepState(Pad *pad, GpioValue value) = 0;
virtual Result IsWakeEventActive(bool *out, Pad *pad) const = 0;

View File

@ -32,7 +32,7 @@
#else
#error "Unknown board for ams::gpio::driver::"
// TODO: #error "Unknown board for ams::gpio::driver::"
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/gpio/gpio_types.hpp>
namespace ams::gpio {
enum GpioPadName : u32 {
GpioPadName_EnableSdCardPower = 2,
};
constexpr inline const DeviceCode DeviceCode_EnableSdCardPower = 0x3C000001;
constexpr inline GpioPadName ConvertToGpioPadName(DeviceCode dc) {
switch (dc.GetInternalValue()) {
case DeviceCode_EnableSdCardPower.GetInternalValue(): return GpioPadName_EnableSdCardPower;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
constexpr inline DeviceCode ConvertToDeviceCode(GpioPadName gpn) {
switch (gpn) {
case GpioPadName_EnableSdCardPower: return DeviceCode_EnableSdCardPower;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}

View File

@ -20,5 +20,5 @@
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
#include <stratosphere/gpio/gpio_pad_name.board.nintendo_nx.hpp>
#else
/* Error? */
#include <stratosphere/gpio/gpio_pad_name.generic.hpp>
#endif

View File

@ -31,7 +31,7 @@
#else
#error "Unknown board for ams::i2c::driver::"
// TODO: #error "Unknown board for ams::i2c::driver::"
#endif

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/i2c/i2c_types.hpp>
namespace ams::i2c {
enum I2cBus {
I2cBus_I2c1 = 0,
};
constexpr inline const DeviceCode DeviceCode_I2c1 = 0x02000001;
constexpr inline DeviceCode ConvertToDeviceCode(I2cBus bus) {
switch (bus) {
case I2cBus_I2c1: return DeviceCode_I2c1;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
constexpr inline DeviceCode ConvertToI2cBus(DeviceCode dc) {
switch (dc.GetInternalValue()) {
case DeviceCode_I2c1.GetInternalValue(): return I2cBus_I2c1;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
enum I2cDevice : u32 {
I2cDevice_ClassicController = 0,
};
/* TODO: Better place for this? */
constexpr inline const DeviceCode DeviceCode_ClassicController = 0x350000C9;
constexpr inline DeviceCode ConvertToDeviceCode(I2cDevice dv) {
switch (dv) {
case I2cDevice_ClassicController: return DeviceCode_ClassicController;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
constexpr inline I2cDevice ConvertToI2cDevice(DeviceCode dc) {
switch (dc.GetInternalValue()) {
case DeviceCode_ClassicController.GetInternalValue(): return I2cDevice_ClassicController;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
constexpr bool IsPowerBusDeviceCode(DeviceCode device_code) {
switch (device_code.GetInternalValue()) {
default:
return false;
}
}
}

View File

@ -20,5 +20,5 @@
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
#include <stratosphere/i2c/i2c_device_name.board.nintendo_nx.hpp>
#else
/* Error? */
#include <stratosphere/i2c/i2c_device_name.generic.hpp>
#endif

Some files were not shown because too many files have changed in this diff Show More