mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
fs: modernize mount utils
This commit is contained in:
parent
7004ad3d7f
commit
901bed6350
5 changed files with 100 additions and 75 deletions
|
@ -26,21 +26,25 @@ namespace ams::fs {
|
|||
constexpr inline char Dot = '.';
|
||||
constexpr inline char NullTerminator = '\x00';
|
||||
|
||||
constexpr inline char UnsupportedDirectorySeparator = '\\';
|
||||
constexpr inline char AlternateDirectorySeparator = '\\';
|
||||
}
|
||||
|
||||
class PathTool {
|
||||
public:
|
||||
static constexpr const char RootPath[] = "/";
|
||||
public:
|
||||
static constexpr inline bool IsUnsupportedSeparator(char c) {
|
||||
return c == StringTraits::UnsupportedDirectorySeparator;
|
||||
static constexpr inline bool IsAlternateSeparator(char c) {
|
||||
return c == StringTraits::AlternateDirectorySeparator;
|
||||
}
|
||||
|
||||
static constexpr inline bool IsSeparator(char c) {
|
||||
return c == StringTraits::DirectorySeparator;
|
||||
}
|
||||
|
||||
static constexpr inline bool IsAnySeparator(char c) {
|
||||
return IsSeparator(c) || IsAlternateSeparator(c);
|
||||
}
|
||||
|
||||
static constexpr inline bool IsNullTerminator(char c) {
|
||||
return c == StringTraits::NullTerminator;
|
||||
}
|
||||
|
@ -61,6 +65,10 @@ namespace ams::fs {
|
|||
return IsWindowsDriveCharacter(p[0]) && IsDriveSeparator(p[1]);
|
||||
}
|
||||
|
||||
static constexpr inline bool IsUnc(const char *p) {
|
||||
return (IsSeparator(p[0]) && IsSeparator(p[1])) || (IsAlternateSeparator(p[0]) && IsAlternateSeparator(p[1]));
|
||||
}
|
||||
|
||||
static constexpr inline bool IsCurrentDirectory(const char *p) {
|
||||
return IsDot(p[0]) && (IsSeparator(p[1]) || IsNullTerminator(p[1]));
|
||||
}
|
||||
|
|
|
@ -33,47 +33,36 @@ namespace ams::fs::impl {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Result GetMountNameImpl(MountName &out, const char *path) {
|
||||
Result GetMountNameAndSubPath(MountName *out_mount_name, const char **out_sub_path, const char *path) {
|
||||
/* Handle the Host-path case. */
|
||||
if (PathTool::IsWindowsAbsolutePath(path) || PathTool::IsUnc(path)) {
|
||||
std::strncpy(out_mount_name->str, HostRootFileSystemMountName, MountNameLengthMax);
|
||||
out_mount_name->str[MountNameLengthMax] = '\x00';
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
/* Locate the drive separator. */
|
||||
const char *drive_separator = FindMountNameDriveSeparator(path);
|
||||
R_UNLESS(drive_separator != nullptr, fs::ResultInvalidMountName());
|
||||
|
||||
/* Ensure the mount name isn't too long. */
|
||||
const size_t len = drive_separator - path;
|
||||
R_UNLESS(len + 1 <= sizeof(MountName), fs::ResultInvalidMountName());
|
||||
R_UNLESS(len <= MountNameLengthMax, fs::ResultInvalidMountName());
|
||||
|
||||
std::memcpy(out.str, path, len);
|
||||
out.str[len] = StringTraits::NullTerminator;
|
||||
/* Ensure the result sub-path is valid. */
|
||||
const char *sub_path = drive_separator + 1;
|
||||
R_UNLESS(!PathTool::IsNullTerminator(sub_path[0]), fs::ResultInvalidMountName());
|
||||
R_UNLESS(PathTool::IsAnySeparator(sub_path[0]), fs::ResultInvalidPathFormat());
|
||||
|
||||
/* Set output. */
|
||||
std::memcpy(out_mount_name->str, path, len);
|
||||
out_mount_name->str[len] = StringTraits::NullTerminator;
|
||||
*out_sub_path = sub_path;
|
||||
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;
|
||||
|
@ -118,12 +107,17 @@ namespace ams::fs::impl {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FindFileSystem(FileSystemAccessor **out, const char *path) {
|
||||
R_UNLESS(path != nullptr, fs::ResultInvalidPath());
|
||||
Result FindFileSystem(FileSystemAccessor **out_accessor, const char **out_sub_path, const char *path) {
|
||||
R_UNLESS(out_accessor != nullptr, fs::ResultUnexpectedInFindFileSystemA());
|
||||
R_UNLESS(out_sub_path != nullptr, fs::ResultUnexpectedInFindFileSystemA());
|
||||
R_UNLESS(path != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
R_UNLESS(strncmp(path, HostRootFileSystemMountName, strnlen(HostRootFileSystemMountName, sizeof(MountName))) != 0, fs::ResultInvalidPathFormat());
|
||||
R_UNLESS(strncmp(path, HostRootFileSystemMountName, strnlen(HostRootFileSystemMountName, sizeof(MountName))) != 0, fs::ResultNotMounted());
|
||||
|
||||
return impl::Find(out, GetMountName(path).str);
|
||||
MountName mount_name;
|
||||
R_TRY(GetMountNameAndSubPath(std::addressof(mount_name), out_sub_path, path));
|
||||
|
||||
return impl::Find(out_accessor, mount_name.str);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -147,15 +141,21 @@ namespace ams::fs {
|
|||
}
|
||||
|
||||
Result ConvertToFsCommonPath(char *dst, size_t dst_size, const char *src) {
|
||||
/* Get the mount name for the path. */
|
||||
MountName mount_name = impl::GetMountName(src);
|
||||
/* Ensure neither argument is nullptr. */
|
||||
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
|
||||
R_UNLESS(src != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Get the mount name and sub path for the path. */
|
||||
MountName mount_name;
|
||||
const char *sub_path;
|
||||
R_TRY(impl::GetMountNameAndSubPath(std::addressof(mount_name), std::addressof(sub_path), 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));
|
||||
const auto common_path_len = std::snprintf(dst + mount_name_len, dst_size - mount_name_len, "%s", sub_path);
|
||||
|
||||
R_UNLESS(static_cast<size_t>(common_path_len) < dst_size - mount_name_len, fs::ResultTooLongPath());
|
||||
return ResultSuccess();
|
||||
|
|
|
@ -20,9 +20,8 @@ namespace ams::fs::impl {
|
|||
|
||||
class FileSystemAccessor;
|
||||
|
||||
Result FindFileSystem(FileSystemAccessor **out, const char *path);
|
||||
Result FindFileSystem(FileSystemAccessor **out_accessor, const char **out_sub_path, const char *path);
|
||||
|
||||
const char *GetSubPath(const char *path);
|
||||
bool IsWindowsDrive(const char *name);
|
||||
bool IsReservedMountName(const char *name);
|
||||
Result CheckMountName(const char *name);
|
||||
|
|
|
@ -34,74 +34,85 @@ namespace ams::fs {
|
|||
|
||||
Result CreateFile(const char* path, s64 size, int option) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->CreateFile(impl::GetSubPath(path), size, option);
|
||||
return accessor->CreateFile(sub_path, size, option);
|
||||
}
|
||||
|
||||
Result DeleteFile(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->DeleteFile(impl::GetSubPath(path));
|
||||
return accessor->DeleteFile(sub_path);
|
||||
}
|
||||
|
||||
Result CreateDirectory(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->CreateDirectory(impl::GetSubPath(path));
|
||||
return accessor->CreateDirectory(sub_path);
|
||||
}
|
||||
|
||||
Result DeleteDirectory(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->DeleteDirectory(impl::GetSubPath(path));
|
||||
return accessor->DeleteDirectory(sub_path);
|
||||
}
|
||||
|
||||
Result DeleteDirectoryRecursively(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->DeleteDirectoryRecursively(impl::GetSubPath(path));
|
||||
return accessor->DeleteDirectoryRecursively(sub_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));
|
||||
const char *old_sub_path;
|
||||
const char *new_sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(old_accessor), std::addressof(old_sub_path), old_path));
|
||||
R_TRY(impl::FindFileSystem(std::addressof(new_accessor), std::addressof(new_sub_path), new_path));
|
||||
|
||||
R_UNLESS(old_accessor == new_accessor, fs::ResultRenameToOtherFileSystem());
|
||||
return old_accessor->RenameFile(impl::GetSubPath(old_path), impl::GetSubPath(new_path));
|
||||
return old_accessor->RenameFile(old_sub_path, new_sub_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));
|
||||
const char *old_sub_path;
|
||||
const char *new_sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(old_accessor), std::addressof(old_sub_path), old_path));
|
||||
R_TRY(impl::FindFileSystem(std::addressof(new_accessor), std::addressof(new_sub_path), new_path));
|
||||
|
||||
R_UNLESS(old_accessor == new_accessor, fs::ResultRenameToOtherFileSystem());
|
||||
return old_accessor->RenameDirectory(impl::GetSubPath(old_path), impl::GetSubPath(new_path));
|
||||
return old_accessor->RenameDirectory(old_sub_path, new_sub_path);
|
||||
}
|
||||
|
||||
Result GetEntryType(DirectoryEntryType *out, const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->GetEntryType(out, impl::GetSubPath(path));
|
||||
return accessor->GetEntryType(out, sub_path);
|
||||
}
|
||||
|
||||
Result OpenFile(FileHandle *out_file, const char *path, int mode) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
R_UNLESS(out_file != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
std::unique_ptr<impl::FileAccessor> file_accessor;
|
||||
R_TRY(accessor->OpenFile(std::addressof(file_accessor), impl::GetSubPath(path), static_cast<OpenMode>(mode)));
|
||||
R_TRY(accessor->OpenFile(std::addressof(file_accessor), sub_path, static_cast<OpenMode>(mode)));
|
||||
|
||||
out_file->handle = file_accessor.release();
|
||||
return ResultSuccess();
|
||||
|
@ -109,12 +120,13 @@ namespace ams::fs {
|
|||
|
||||
Result OpenDirectory(DirectoryHandle *out_dir, const char *path, int mode) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
R_UNLESS(out_dir != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
std::unique_ptr<impl::DirectoryAccessor> dir_accessor;
|
||||
R_TRY(accessor->OpenDirectory(std::addressof(dir_accessor), impl::GetSubPath(path), static_cast<OpenDirectoryMode>(mode)));
|
||||
R_TRY(accessor->OpenDirectory(std::addressof(dir_accessor), sub_path, static_cast<OpenDirectoryMode>(mode)));
|
||||
|
||||
out_dir->handle = dir_accessor.release();
|
||||
return ResultSuccess();
|
||||
|
@ -122,38 +134,43 @@ namespace ams::fs {
|
|||
|
||||
Result CleanDirectoryRecursively(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->CleanDirectoryRecursively(impl::GetSubPath(path));
|
||||
return accessor->CleanDirectoryRecursively(sub_path);
|
||||
}
|
||||
|
||||
Result GetFreeSpaceSize(s64 *out, const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->GetFreeSpaceSize(out, impl::GetSubPath(path));
|
||||
return accessor->GetFreeSpaceSize(out, sub_path);
|
||||
}
|
||||
|
||||
Result GetTotalSpaceSize(s64 *out, const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->GetTotalSpaceSize(out, impl::GetSubPath(path));
|
||||
return accessor->GetTotalSpaceSize(out, sub_path);
|
||||
}
|
||||
|
||||
|
||||
Result SetConcatenationFileAttribute(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->QueryEntry(nullptr, 0, nullptr, 0, fsa::QueryId::SetConcatenationFileAttribute, impl::GetSubPath(path));
|
||||
return accessor->QueryEntry(nullptr, 0, nullptr, 0, fsa::QueryId::SetConcatenationFileAttribute, sub_path);
|
||||
}
|
||||
|
||||
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), path));
|
||||
const char *sub_path;
|
||||
R_TRY(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), path));
|
||||
|
||||
return accessor->GetFileTimeStampRaw(out, impl::GetSubPath(path));
|
||||
return accessor->GetFileTimeStampRaw(out, sub_path);
|
||||
}
|
||||
|
||||
Result OpenFile(FileHandle *out, std::unique_ptr<fsa::IFile> &&file, int mode) {
|
||||
|
|
|
@ -198,6 +198,7 @@ namespace ams::fs {
|
|||
R_DEFINE_ERROR_RESULT(GameCardLogoDataCorrupted, 4781);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(Unexpected, 5000, 5999);
|
||||
R_DEFINE_ERROR_RESULT(UnexpectedInFindFileSystemA, 5319);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(PreconditionViolation, 6000, 6499);
|
||||
R_DEFINE_ERROR_RANGE(InvalidArgument, 6001, 6199);
|
||||
|
|
Loading…
Add table
Reference in a new issue