diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 1daffe930..95256ae54 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -25,6 +25,7 @@ #include "fs/fs_remote_storage.hpp" #include "fs/fs_file_storage.hpp" #include "fs/fs_query_range.hpp" +#include "fs/impl/fs_common_mount_name.hpp" #include "fs/fs_mount.hpp" #include "fs/fs_path_tool.hpp" #include "fs/fs_path_utils.hpp" diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_directory.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_directory.hpp index 65e84ff01..c2e3a76b1 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_directory.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_directory.hpp @@ -22,4 +22,12 @@ namespace ams::fs { using DirectoryEntry = ::FsDirectoryEntry; + struct DirectoryHandle { + void *handle; + }; + + Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries); + Result GetDirectoryEntryCount(s64 *out, DirectoryHandle handle); + void CloseDirectory(DirectoryHandle handle); + } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_file.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_file.hpp index f8515f1f7..51fab7070 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_file.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_file.hpp @@ -60,4 +60,19 @@ namespace ams::fs { static_assert(std::is_pod::value && sizeof(WriteOption) == sizeof(u32)); + struct FileHandle { + void *handle; + }; + + Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option); + Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size); + Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option); + Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size); + Result GetFileSize(s64 *out, FileHandle handle); + Result FlushFile(FileHandle handle); + Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option); + Result SetFileSize(FileHandle handle, s64 size); + int GetFileOpenMode(FileHandle handle); + void CloseFile(FileHandle handle); + } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_filesystem.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_filesystem.hpp index 2c8767f0f..79a77c505 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_filesystem.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_filesystem.hpp @@ -18,6 +18,12 @@ namespace ams::fs { + namespace fsa { + + class IFile; + + } + enum OpenMode { OpenMode_Read = ::FsOpenMode_Read, OpenMode_Write = ::FsOpenMode_Write, @@ -49,4 +55,27 @@ namespace ams::fs { using FileTimeStampRaw = ::FsTimeStampRaw; + struct FileHandle; + struct DirectoryHandle; + + Result CreateFile(const char *path, s64 size); + Result CreateFile(const char* path, s64 size, int option); + Result DeleteFile(const char *path); + Result CreateDirectory(const char *path); + Result DeleteDirectory(const char *path); + Result DeleteDirectoryRecursively(const char *path); + Result RenameFile(const char *old_path, const char *new_path); + Result RenameDirectory(const char *old_path, const char *new_path); + Result GetEntryType(DirectoryEntryType *out, const char *path); + Result OpenFile(FileHandle *out_file, const char *path, int mode); + Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode); + Result CleanDirectoryRecursively(const char *path); + Result GetFreeSpaceSize(s64 *out, const char *path); + Result GetTotalSpaceSize(s64 *out, const char *path); + + Result SetConcatenationFileAttribute(const char *path); + Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path); + + Result OpenFile(FileHandle *out, std::unique_ptr &&file, int mode); + } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_path_tool.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_path_tool.hpp index 2344dac91..28c180558 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_path_tool.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_path_tool.hpp @@ -26,12 +26,17 @@ namespace ams::fs { constexpr inline char Dot = '.'; constexpr inline char NullTerminator = '\x00'; + constexpr inline char UnsupportedDirectorySeparator = '/'; } class PathTool { public: static constexpr const char RootPath[] = "/"; public: + static constexpr inline bool IsUnsupportedSeparator(char c) { + return c == StringTraits::UnsupportedDirectorySeparator; + } + static constexpr inline bool IsSeparator(char c) { return c == StringTraits::DirectorySeparator; } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_query_range.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_query_range.hpp index f6255edde..6777f03cf 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_query_range.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_query_range.hpp @@ -15,6 +15,7 @@ */ #pragma once #include "fs_common.hpp" +#include "fs_file.hpp" namespace ams::fs { @@ -42,4 +43,6 @@ namespace ams::fs { using FileQueryRangeInfo = QueryRangeInfo; using StorageQueryRangeInfo = QueryRangeInfo; + Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size); + } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_remote_filesystem.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_remote_filesystem.hpp index f12a02a4b..911097048 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_remote_filesystem.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_remote_filesystem.hpp @@ -87,7 +87,7 @@ namespace ams::fs { } }; - class RemoteFileSystem : public fsa::IFileSystem { + class RemoteFileSystem : public fsa::IFileSystem, public impl::Newable { private: std::unique_ptr<::FsFileSystem, impl::Deleter> base_fs; public: diff --git a/libraries/libstratosphere/include/stratosphere/fs/impl/fs_common_mount_name.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_common_mount_name.hpp new file mode 100644 index 000000000..adeec7305 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_common_mount_name.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +namespace ams::fs::impl { + + /* Delimiting of mount names. */ + constexpr inline const char ReservedMountNamePrefixCharacter = '@'; + constexpr inline const char *MountNameDelimiter = ":/"; + + /* Filesystem names. */ + constexpr inline const char *HostRootFileSystemMountName = "@Host"; + constexpr inline const char *SdCardFileSystemMountName = "@Sdcard"; + constexpr inline const char *GameCardFileSystemMountName = "@Gc"; + + constexpr inline size_t GameCardFileSystemMountNameSuffixLength = 1; + constexpr inline const char *GameCardFileSystemMountNameUpdateSuffix = "U"; + constexpr inline const char *GameCardFileSystemMountNameNormalSuffix = "N"; + constexpr inline const char *GameCardFileSystemMountNameSecureSuffix = "S"; + + /* Built-in storage names. */ + constexpr inline const char *BisCalibrationFilePartitionMountName = "@CalibFile"; + constexpr inline const char *BisSafeModePartitionMountName = "@Safe"; + constexpr inline const char *BisUserPartitionMountName = "@User"; + constexpr inline const char *BisSystemPartitionMountName = "@System"; + + /* Registered update partition. */ + constexpr inline const char *RegisteredUpdatePartitionMountName = "@RegUpdate"; + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.cpp b/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.cpp new file mode 100644 index 000000000..ea736a9b6 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fs_filesystem_accessor.hpp" +#include "fs_mount_utils.hpp" +#include "fs_user_mount_table.hpp" + +namespace ams::fs::impl { + + namespace { + + const char *FindMountNameDriveSeparator(const char *path) { + for (const char *cur = path; cur < path + MountNameLengthMax + 1; cur++) { + if (PathTool::IsDriveSeparator(*cur)) { + return cur; + } else if (PathTool::IsNullTerminator(*cur)) { + break; + } + } + return nullptr; + } + + Result GetMountNameImpl(MountName &out, const char *path) { + const char *drive_separator = FindMountNameDriveSeparator(path); + R_UNLESS(drive_separator != nullptr, fs::ResultInvalidMountName()); + + const size_t len = drive_separator - path; + R_UNLESS(len + 1 <= sizeof(MountName), fs::ResultInvalidMountName()); + + std::memcpy(out.str, path, len); + out.str[len] = StringTraits::NullTerminator; + return ResultSuccess(); + } + + } + + MountName GetMountName(const char *path) { + MountName mount_name; + + if (IsWindowsDrive(path)) { + std::strncpy(mount_name.str, HostRootFileSystemMountName, MountNameLengthMax); + mount_name.str[MountNameLengthMax] = StringTraits::NullTerminator; + } else { + R_ABORT_UNLESS(GetMountNameImpl(mount_name, path)); + } + + return mount_name; + } + + const char *GetSubPath(const char *path) { + if (IsWindowsDrive(path)) { + return path; + } + + const char *sub_path = path; + while (!PathTool::IsDriveSeparator(*sub_path)) { + sub_path++; + } + + AMS_ABORT_UNLESS(PathTool::IsSeparator(sub_path[1]) || PathTool::IsUnsupportedSeparator(sub_path[1])); + return sub_path + 1; + } + + bool IsValidMountName(const char *name) { + if (PathTool::IsNullTerminator(*name)) { + return false; + } + + if (PathTool::IsWindowsDriveCharacter(name[0]) && PathTool::IsNullTerminator(name[1])) { + return false; + } + + size_t len = 0; + for (const char *cur = name; !PathTool::IsNullTerminator(*cur); cur++) { + if (PathTool::IsDriveSeparator(*cur) || PathTool::IsSeparator(*cur)) { + return false; + } + + if ((++len) > MountNameLengthMax) { + return false; + } + } + + /* TODO: N validates that the mount name decodes via utf-8 here. */ + return true; + } + + bool IsWindowsDrive(const char *name) { + return PathTool::IsWindowsAbsolutePath(name); + } + + bool IsReservedMountName(const char *name) { + return name[0] != ReservedMountNamePrefixCharacter; + } + + Result CheckMountName(const char *name) { + R_TRY(CheckMountNameAllowingReserved(name)); + R_UNLESS(!impl::IsReservedMountName(name), fs::ResultInvalidMountName()); + return ResultSuccess(); + } + + Result CheckMountNameAllowingReserved(const char *name) { + R_UNLESS(name != nullptr, fs::ResultInvalidMountName()); + R_UNLESS(impl::IsValidMountName(name), fs::ResultInvalidMountName()); + return ResultSuccess(); + } + + Result FindFileSystem(FileSystemAccessor **out, const char *path) { + R_UNLESS(path != nullptr, fs::ResultInvalidPath()); + + R_UNLESS(strncmp(path, HostRootFileSystemMountName, strnlen(HostRootFileSystemMountName, sizeof(MountName))) != 0, fs::ResultInvalidPathFormat()); + + return impl::Find(out, GetMountName(path).str); + } + +} + +namespace ams::fs { + + namespace { + + Result UnmountImpl(const char *name) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::Find(std::addressof(accessor), name)); + + if (accessor->IsFileDataCacheAttachable()) { + /* TODO: Data cache purge */ + } + + impl::Unregister(name); + return ResultSuccess(); + } + + } + + Result ConvertToFsCommonPath(char *dst, size_t dst_size, const char *src) { + /* Get the mount name for the path. */ + MountName mount_name = impl::GetMountName(src); + + impl::FileSystemAccessor *accessor; + R_TRY(impl::Find(std::addressof(accessor), mount_name.str)); + R_TRY(accessor->GetCommonMountName(dst, dst_size)); + + const auto mount_name_len = strnlen(dst, dst_size); + const auto common_path_len = std::snprintf(dst + mount_name_len, dst_size - mount_name_len, "%s", impl::GetSubPath(src)); + + R_UNLESS(static_cast(common_path_len) < dst_size - mount_name_len, fs::ResultTooLongPath()); + return ResultSuccess(); + } + + void Unmount(const char *mount_name) { + R_ABORT_UNLESS(UnmountImpl(mount_name)); + } + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.hpp b/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.hpp new file mode 100644 index 000000000..b4c191aa2 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fsa/fs_mount_utils.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::fs::impl { + + class FileSystemAccessor; + + Result FindFileSystem(FileSystemAccessor **out, const char *path); + + const char *GetSubPath(const char *path); + bool IsWindowsDrive(const char *name); + bool IsReservedMountName(const char *name); + Result CheckMountName(const char *name); + Result CheckMountNameAllowingReserved(const char *name); + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_user_directory.cpp b/libraries/libstratosphere/source/fs/fsa/fs_user_directory.cpp new file mode 100644 index 000000000..e29957c60 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fsa/fs_user_directory.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fs_directory_accessor.hpp" +#include "fs_filesystem_accessor.hpp" + +namespace ams::fs { + + namespace { + + ALWAYS_INLINE impl::DirectoryAccessor *Get(DirectoryHandle handle) { + return reinterpret_cast(handle.handle); + } + + } + + Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries) { + return Get(handle)->Read(out_count, out_entries, max_entries); + } + + Result GetDirectoryEntryCount(s64 *out, DirectoryHandle handle) { + return Get(handle)->GetEntryCount(out); + } + + void CloseDirectory(DirectoryHandle handle) { + delete Get(handle); + } + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp b/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp new file mode 100644 index 000000000..02ccddb5a --- /dev/null +++ b/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fs_file_accessor.hpp" +#include "fs_filesystem_accessor.hpp" + +namespace ams::fs { + + namespace { + + ALWAYS_INLINE impl::FileAccessor *Get(FileHandle handle) { + return reinterpret_cast(handle.handle); + } + + } + + Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { + size_t read_size; + R_TRY(ReadFile(std::addressof(size), handle, offset, buffer, size, option)); + R_UNLESS(read_size == size, fs::ResultOutOfRange()); + return ResultSuccess(); + } + + Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) { + return ReadFile(handle, offset, buffer, size, ReadOption()); + } + + Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { + return Get(handle)->Read(out, offset, buffer, size, option); + } + + Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) { + return ReadFile(out, handle, offset, buffer, size, ReadOption()); + } + + Result GetFileSize(s64 *out, FileHandle handle) { + return Get(handle)->GetSize(out); + } + + Result FlushFile(FileHandle handle) { + return Get(handle)->Flush(); + } + + Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) { + return Get(handle)->Write(offset, buffer, size, option); + } + + Result SetFileSize(FileHandle handle, s64 size) { + return Get(handle)->SetSize(size); + } + + int GetFileOpenMode(FileHandle handle) { + return Get(handle)->GetOpenMode(); + } + + void CloseFile(FileHandle handle) { + delete Get(handle); + } + + Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size) { + return Get(handle)->OperateRange(out, sizeof(*out), OperationId::QueryRange, offset, size, nullptr, 0); + } + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_user_filesystem.cpp b/libraries/libstratosphere/source/fs/fsa/fs_user_filesystem.cpp new file mode 100644 index 000000000..66c31c545 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fsa/fs_user_filesystem.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software { + + } + you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY { + + } + without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fs_filesystem_accessor.hpp" +#include "fs_file_accessor.hpp" +#include "fs_directory_accessor.hpp" +#include "fs_mount_utils.hpp" +#include "fs_user_mount_table.hpp" + +namespace ams::fs { + + Result CreateFile(const char *path, s64 size) { + return CreateFile(path, size, 0); + } + + Result CreateFile(const char* path, s64 size, int option) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->CreateFile(impl::GetSubPath(path), size, option); + } + + Result DeleteFile(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->DeleteFile(impl::GetSubPath(path)); + } + + Result CreateDirectory(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->CreateDirectory(impl::GetSubPath(path)); + } + + Result DeleteDirectory(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->DeleteDirectory(impl::GetSubPath(path)); + } + + Result DeleteDirectoryRecursively(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->DeleteDirectoryRecursively(impl::GetSubPath(path)); + } + + Result RenameFile(const char *old_path, const char *new_path) { + impl::FileSystemAccessor *old_accessor; + impl::FileSystemAccessor *new_accessor; + R_TRY(impl::FindFileSystem(std::addressof(old_accessor), old_path)); + R_TRY(impl::FindFileSystem(std::addressof(new_accessor), new_path)); + + R_UNLESS(old_accessor == new_accessor, fs::ResultRenameToOtherFileSystem()); + return old_accessor->RenameFile(impl::GetSubPath(old_path), impl::GetSubPath(new_path)); + } + + Result RenameDirectory(const char *old_path, const char *new_path) { + impl::FileSystemAccessor *old_accessor; + impl::FileSystemAccessor *new_accessor; + R_TRY(impl::FindFileSystem(std::addressof(old_accessor), old_path)); + R_TRY(impl::FindFileSystem(std::addressof(new_accessor), new_path)); + + R_UNLESS(old_accessor == new_accessor, fs::ResultRenameToOtherFileSystem()); + return old_accessor->RenameDirectory(impl::GetSubPath(old_path), impl::GetSubPath(new_path)); + } + + Result GetEntryType(DirectoryEntryType *out, const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->GetEntryType(out, impl::GetSubPath(path)); + } + + Result OpenFile(FileHandle *out_file, const char *path, int mode) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument()); + + std::unique_ptr file_accessor; + R_TRY(accessor->OpenFile(std::addressof(file_accessor), impl::GetSubPath(path), static_cast(mode))); + + out_file->handle = file_accessor.release(); + return ResultSuccess(); + } + + Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument()); + + std::unique_ptr dir_accessor; + R_TRY(accessor->OpenDirectory(std::addressof(dir_accessor), impl::GetSubPath(path), static_cast(mode))); + + out_dir->handle = dir_accessor.release(); + return ResultSuccess(); + } + + Result CleanDirectoryRecursively(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->CleanDirectoryRecursively(impl::GetSubPath(path)); + } + + Result GetFreeSpaceSize(s64 *out, const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->GetFreeSpaceSize(out, impl::GetSubPath(path)); + } + + Result GetTotalSpaceSize(s64 *out, const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->GetTotalSpaceSize(out, impl::GetSubPath(path)); + } + + + Result SetConcatenationFileAttribute(const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->QueryEntry(nullptr, 0, nullptr, 0, fsa::QueryId::SetConcatenationFileAttribute, impl::GetSubPath(path)); + } + + Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path) { + impl::FileSystemAccessor *accessor; + R_TRY(impl::FindFileSystem(std::addressof(accessor), path)); + + return accessor->GetFileTimeStampRaw(out, impl::GetSubPath(path)); + } + + Result OpenFile(FileHandle *out, std::unique_ptr &&file, int mode) { + R_UNLESS(out != nullptr, fs::ResultNullptrArgument()); + + std::unique_ptr file_accessor(new impl::FileAccessor(std::move(file), nullptr, static_cast(mode))); + R_UNLESS(file_accessor != nullptr, fs::ResultAllocationFailureInUserFileSystem()); + out->handle = file_accessor.release(); + + return ResultSuccess(); + } + + +} diff --git a/libraries/libvapours/include/vapours/results/fs_results.hpp b/libraries/libvapours/include/vapours/results/fs_results.hpp index aba056808..621f1f3ff 100644 --- a/libraries/libvapours/include/vapours/results/fs_results.hpp +++ b/libraries/libvapours/include/vapours/results/fs_results.hpp @@ -56,6 +56,7 @@ namespace ams::fs { R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366); R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367); R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407); + R_DEFINE_ERROR_RESULT(AllocationFailureInUserFileSystem, 3420); R_DEFINE_ERROR_RANGE(MmcAccessFailed, 3500, 3999);