mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-20 18:42:40 +02:00
ams: support building unit test programs on windows/linux/macos
This commit is contained in:
parent
c5ae3c2449
commit
d7a9c7ec4c
10
Makefile
10
Makefile
@ -1,10 +0,0 @@
|
||||
ATMOSPHERE_LIBRARIES := libmesosphere libstratosphere libexosphere
|
||||
|
||||
TOPTARGETS := all clean
|
||||
|
||||
$(TOPTARGETS): $(ATMOSPHERE_LIBRARIES)
|
||||
|
||||
$(ATMOSPHERE_LIBRARIES):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS)
|
||||
|
||||
.PHONY: $(TOPTARGETS) $(ATMOSPHERE_LIBRARIES)
|
@ -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
|
28
config/arch/arm64/base_rules
Normal file
28
config/arch/arm64/base_rules
Normal 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)
|
52
config/arch/arm64/base_tools
Normal file
52
config/arch/arm64/base_tools
Normal 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
|
5
config/arch/arm64/cpu/generic_arm64/cpu.mk
Normal file
5
config/arch/arm64/cpu/generic_arm64/cpu.mk
Normal 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
7
config/arch/x64/arch.mk
Normal 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 +=
|
28
config/arch/x64/base_rules
Normal file
28
config/arch/x64/base_rules
Normal 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)
|
52
config/arch/x64/base_tools
Normal file
52
config/arch/x64/base_tools
Normal 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
|
5
config/arch/x64/cpu/generic_x64/cpu.mk
Normal file
5
config/arch/x64/cpu/generic_x64/cpu.mk
Normal 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 +=
|
19
config/board/generic/linux/board.mk
Normal file
19
config/board/generic/linux/board.mk
Normal 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
|
23
config/board/generic/macos/board.mk
Normal file
23
config/board/generic/macos/board.mk
Normal 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
|
5
config/board/generic/windows/board.mk
Normal file
5
config/board/generic/windows/board.mk
Normal file
@ -0,0 +1,5 @@
|
||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_BOARD_GENERIC_WINDOWS
|
||||
export ATMOSPHERE_SETTINGS +=
|
||||
export ATMOSPHERE_CFLAGS +=
|
||||
export ATMOSPHERE_CXXFLAGS +=
|
||||
export ATMOSPHERE_ASFLAGS +=
|
138
config/common.mk
138
config/common.mk
@ -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
5
config/os/linux/os.mk
Normal 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
5
config/os/macos/os.mk
Normal 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
5
config/os/windows/os.mk
Normal file
@ -0,0 +1,5 @@
|
||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
|
||||
export ATMOSPHERE_SETTINGS +=
|
||||
export ATMOSPHERE_CFLAGS +=
|
||||
export ATMOSPHERE_CXXFLAGS +=
|
||||
export ATMOSPHERE_ASFLAGS +=
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
123
libmesosphere/libmesosphere.mk
Normal file
123
libmesosphere/libmesosphere.mk
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
@ -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))
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -81,7 +81,7 @@ namespace ams::ddsf {
|
||||
m_session_list.clear();
|
||||
}
|
||||
protected:
|
||||
~IDevice() {
|
||||
virtual ~IDevice() {
|
||||
m_session_list.clear();
|
||||
}
|
||||
public:
|
||||
|
@ -40,7 +40,7 @@ namespace ams::ddsf {
|
||||
m_device_list.clear();
|
||||
}
|
||||
protected:
|
||||
~IDriver() {
|
||||
virtual ~IDriver() {
|
||||
m_device_list.clear();
|
||||
}
|
||||
public:
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
58
libstratosphere/include/stratosphere/fs/fs_host.hpp
Normal file
58
libstratosphere/include/stratosphere/fs/fs_host.hpp
Normal 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();
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
582
libstratosphere/include/stratosphere/fs/fs_path.hpp
Normal file
582
libstratosphere/include/stratosphere/fs/fs_path.hpp
Normal 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));
|
||||
}
|
||||
|
||||
}
|
1210
libstratosphere/include/stratosphere/fs/fs_path_utility.hpp
Normal file
1210
libstratosphere/include/stratosphere/fs/fs_path_utility.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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); }
|
||||
|
@ -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? */
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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__)
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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__) \
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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>);
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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) { /* ... */ }
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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)
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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); }
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#error "Unknown board for ams::gpio::driver::"
|
||||
// TODO: #error "Unknown board for ams::gpio::driver::"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#error "Unknown board for ams::i2c::driver::"
|
||||
// TODO: #error "Unknown board for ams::i2c::driver::"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user